diff options
Diffstat (limited to 'main/openssl/ssl')
-rw-r--r-- | main/openssl/ssl/d1_clnt.c | 13 | ||||
-rw-r--r-- | main/openssl/ssl/d1_srvr.c | 10 | ||||
-rw-r--r-- | main/openssl/ssl/s3_clnt.c | 359 | ||||
-rw-r--r-- | main/openssl/ssl/s3_lib.c | 38 | ||||
-rw-r--r-- | main/openssl/ssl/s3_srvr.c | 540 | ||||
-rw-r--r-- | main/openssl/ssl/ssl.h | 4 | ||||
-rw-r--r-- | main/openssl/ssl/ssl_lib.c | 58 | ||||
-rw-r--r-- | main/openssl/ssl/ssl_sess.c | 12 | ||||
-rw-r--r-- | main/openssl/ssl/tls1.h | 8 |
9 files changed, 613 insertions, 429 deletions
diff --git a/main/openssl/ssl/d1_clnt.c b/main/openssl/ssl/d1_clnt.c index 4fc4e1b9..5ee8f58e 100644 --- a/main/openssl/ssl/d1_clnt.c +++ b/main/openssl/ssl/d1_clnt.c @@ -1440,7 +1440,7 @@ int dtls1_send_client_key_exchange(SSL *s) goto err; } - psk_len = s->psk_client_callback(s, s->ctx->psk_identity_hint, + psk_len = s->psk_client_callback(s, s->session->psk_identity_hint, identity, PSK_MAX_IDENTITY_LEN, psk_or_pre_ms, sizeof(psk_or_pre_ms)); if (psk_len > PSK_MAX_PSK_LEN) @@ -1465,17 +1465,6 @@ int dtls1_send_client_key_exchange(SSL *s) t+=psk_len; s2n(psk_len, t); - if (s->session->psk_identity_hint != NULL) - OPENSSL_free(s->session->psk_identity_hint); - s->session->psk_identity_hint = BUF_strdup(s->ctx->psk_identity_hint); - if (s->ctx->psk_identity_hint != NULL && - s->session->psk_identity_hint == NULL) - { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, - ERR_R_MALLOC_FAILURE); - goto psk_err; - } - if (s->session->psk_identity != NULL) OPENSSL_free(s->session->psk_identity); s->session->psk_identity = BUF_strdup(identity); diff --git a/main/openssl/ssl/d1_srvr.c b/main/openssl/ssl/d1_srvr.c index 9975e208..09f47627 100644 --- a/main/openssl/ssl/d1_srvr.c +++ b/main/openssl/ssl/d1_srvr.c @@ -471,7 +471,7 @@ int dtls1_accept(SSL *s) /* PSK: send ServerKeyExchange if PSK identity * hint if provided */ #ifndef OPENSSL_NO_PSK - || ((alg_k & SSL_kPSK) && s->ctx->psk_identity_hint) + || ((alg_k & SSL_kPSK) && s->session->psk_identity_hint) #endif || (alg_k & (SSL_kEDH|SSL_kDHr|SSL_kDHd)) || (alg_k & SSL_kEECDH) @@ -1288,7 +1288,7 @@ int dtls1_send_server_key_exchange(SSL *s) if (type & SSL_kPSK) { /* reserve size for record length and PSK identity hint*/ - n+=2+strlen(s->ctx->psk_identity_hint); + n+=2+strlen(s->session->psk_identity_hint); } else #endif /* !OPENSSL_NO_PSK */ @@ -1364,9 +1364,9 @@ int dtls1_send_server_key_exchange(SSL *s) if (type & SSL_kPSK) { /* copy PSK identity hint */ - s2n(strlen(s->ctx->psk_identity_hint), p); - strncpy((char *)p, s->ctx->psk_identity_hint, strlen(s->ctx->psk_identity_hint)); - p+=strlen(s->ctx->psk_identity_hint); + s2n(strlen(s->session->psk_identity_hint), p); + strncpy((char *)p, s->session->psk_identity_hint, strlen(s->session->psk_identity_hint)); + p+=strlen(s->session->psk_identity_hint); } #endif diff --git a/main/openssl/ssl/s3_clnt.c b/main/openssl/ssl/s3_clnt.c index f71470a3..b65b12d9 100644 --- a/main/openssl/ssl/s3_clnt.c +++ b/main/openssl/ssl/s3_clnt.c @@ -345,9 +345,10 @@ int ssl3_connect(SSL *s) } #endif /* Check if it is anon DH/ECDH */ - /* or PSK */ + /* or non-RSA PSK */ if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) && - !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) + !((s->s3->tmp.new_cipher->algorithm_auth & SSL_aPSK) && + !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kRSA))) { ret=ssl3_get_server_certificate(s); if (ret <= 0) goto end; @@ -1377,12 +1378,14 @@ int ssl3_get_key_exchange(SSL *s) omitted if no identity hint is sent. Set session->sess_cert anyway to avoid problems later.*/ - if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK) + if (s->s3->tmp.new_cipher->algorithm_auth & SSL_aPSK) { s->session->sess_cert=ssl_sess_cert_new(); - if (s->ctx->psk_identity_hint) - OPENSSL_free(s->ctx->psk_identity_hint); - s->ctx->psk_identity_hint = NULL; + if (s->session->psk_identity_hint) + { + OPENSSL_free(s->session->psk_identity_hint); + s->session->psk_identity_hint = NULL; + } } #endif s->s3->tmp.reuse_message=1; @@ -1425,52 +1428,58 @@ int ssl3_get_key_exchange(SSL *s) EVP_MD_CTX_init(&md_ctx); #ifndef OPENSSL_NO_PSK - if (alg_k & SSL_kPSK) + if (alg_a & SSL_aPSK) { char tmp_id_hint[PSK_MAX_IDENTITY_LEN+1]; al=SSL_AD_HANDSHAKE_FAILURE; n2s(p,i); param_len=i+2; - /* Store PSK identity hint for later use, hint is used - * in ssl3_send_client_key_exchange. Assume that the - * maximum length of a PSK identity hint can be as - * long as the maximum length of a PSK identity. */ - if (i > PSK_MAX_IDENTITY_LEN) - { - SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, - SSL_R_DATA_LENGTH_TOO_LONG); - goto f_err; + if (s->session->psk_identity_hint) + { + OPENSSL_free(s->session->psk_identity_hint); + s->session->psk_identity_hint = NULL; } - if (param_len > n) + if (i != 0) { - al=SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, - SSL_R_BAD_PSK_IDENTITY_HINT_LENGTH); - goto f_err; + /* Store PSK identity hint for later use, hint is used + * in ssl3_send_client_key_exchange. Assume that the + * maximum length of a PSK identity hint can be as + * long as the maximum length of a PSK identity. */ + if (i > PSK_MAX_IDENTITY_LEN) + { + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, + SSL_R_DATA_LENGTH_TOO_LONG); + goto f_err; + } + if (param_len > n) + { + al=SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, + SSL_R_BAD_PSK_IDENTITY_HINT_LENGTH); + goto f_err; + } + /* If received PSK identity hint contains NULL + * characters, the hint is truncated from the first + * NULL. p may not be ending with NULL, so create a + * NULL-terminated string. */ + memcpy(tmp_id_hint, p, i); + memset(tmp_id_hint+i, 0, PSK_MAX_IDENTITY_LEN+1-i); + s->session->psk_identity_hint = BUF_strdup(tmp_id_hint); + if (s->session->psk_identity_hint == NULL) + { + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE); + goto f_err; + } } - /* If received PSK identity hint contains NULL - * characters, the hint is truncated from the first - * NULL. p may not be ending with NULL, so create a - * NULL-terminated string. */ - memcpy(tmp_id_hint, p, i); - memset(tmp_id_hint+i, 0, PSK_MAX_IDENTITY_LEN+1-i); - if (s->ctx->psk_identity_hint != NULL) - OPENSSL_free(s->ctx->psk_identity_hint); - s->ctx->psk_identity_hint = BUF_strdup(tmp_id_hint); - if (s->ctx->psk_identity_hint == NULL) - { - SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE); - goto f_err; - } - p+=i; n-=param_len; } - else #endif /* !OPENSSL_NO_PSK */ + + if (0) {} #ifndef OPENSSL_NO_SRP - if (alg_k & SSL_kSRP) + else if (alg_k & SSL_kSRP) { n2s(p,i); param_len=i+2; @@ -1547,10 +1556,9 @@ int ssl3_get_key_exchange(SSL *s) pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_DSA_SIGN].x509); #endif } - else #endif /* !OPENSSL_NO_SRP */ #ifndef OPENSSL_NO_RSA - if (alg_k & SSL_kRSA) + else if (alg_k & SSL_kRSA) { if ((rsa=RSA_new()) == NULL) { @@ -1599,9 +1607,6 @@ int ssl3_get_key_exchange(SSL *s) s->session->sess_cert->peer_rsa_tmp=rsa; rsa=NULL; } -#else /* OPENSSL_NO_RSA */ - if (0) - ; #endif #ifndef OPENSSL_NO_DH else if (alg_k & SSL_kEDH) @@ -1782,14 +1787,14 @@ int ssl3_get_key_exchange(SSL *s) EC_POINT_free(srvr_ecpoint); srvr_ecpoint = NULL; } - else if (alg_k) +#endif /* !OPENSSL_NO_ECDH */ + + else if (!(alg_k & SSL_kPSK)) { al=SSL_AD_UNEXPECTED_MESSAGE; SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_UNEXPECTED_MESSAGE); goto f_err; } -#endif /* !OPENSSL_NO_ECDH */ - /* p points to the next byte, there are 'n' bytes left */ @@ -1894,8 +1899,9 @@ fprintf(stderr, "USING TLSv1.2 HASH %s\n", EVP_MD_name(md)); } else { - if (!(alg_a & SSL_aNULL) && !(alg_k & SSL_kPSK)) - /* aNULL or kPSK do not need public keys */ + if (!(alg_a & SSL_aNULL) && + /* Among PSK ciphers only RSA_PSK needs a public key */ + !((alg_a & SSL_aPSK) && !(alg_k & SSL_kRSA))) { SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR); goto err; @@ -2297,6 +2303,7 @@ int ssl3_send_client_key_exchange(SSL *s) unsigned char *p,*d; int n; unsigned long alg_k; + unsigned long alg_a; #ifndef OPENSSL_NO_RSA unsigned char *q; EVP_PKEY *pkey=NULL; @@ -2311,7 +2318,11 @@ int ssl3_send_client_key_exchange(SSL *s) unsigned char *encodedPoint = NULL; int encoded_pt_len = 0; BN_CTX * bn_ctx = NULL; -#endif +#ifndef OPENSSL_NO_PSK + unsigned int psk_len = 0; + unsigned char psk[PSK_MAX_PSK_LEN]; +#endif /* OPENSSL_NO_PSK */ +#endif /* OPENSSL_NO_ECDH */ if (s->state == SSL3_ST_CW_KEY_EXCH_A) { @@ -2319,7 +2330,89 @@ int ssl3_send_client_key_exchange(SSL *s) p= &(d[4]); alg_k=s->s3->tmp.new_cipher->algorithm_mkey; + alg_a=s->s3->tmp.new_cipher->algorithm_auth; + +#ifndef OPENSSL_NO_PSK + if (alg_a & SSL_aPSK) + { + char identity[PSK_MAX_IDENTITY_LEN + 1]; + size_t identity_len; + unsigned char *t = NULL; + unsigned char pre_ms[PSK_MAX_PSK_LEN*2+4]; + unsigned int pre_ms_len = 0; + int psk_err = 1; + + n = 0; + if (s->psk_client_callback == NULL) + { + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, + SSL_R_PSK_NO_CLIENT_CB); + goto err; + } + + memset(identity, 0, sizeof(identity)); + psk_len = s->psk_client_callback(s, s->session->psk_identity_hint, + identity, sizeof(identity), psk, sizeof(psk)); + if (psk_len > PSK_MAX_PSK_LEN) + { + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, + ERR_R_INTERNAL_ERROR); + goto psk_err; + } + else if (psk_len == 0) + { + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, + SSL_R_PSK_IDENTITY_NOT_FOUND); + goto psk_err; + } + identity_len = strnlen(identity, sizeof(identity)); + if (identity_len > PSK_MAX_IDENTITY_LEN) + { + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, + ERR_R_INTERNAL_ERROR); + goto psk_err; + } + if (!(alg_k & SSL_kEECDH)) + { + /* Create the shared secret now if we're not using ECDHE-PSK.*/ + pre_ms_len = 2+psk_len+2+psk_len; + t = pre_ms; + s2n(psk_len, t); + memset(t, 0, psk_len); + t+=psk_len; + s2n(psk_len, t); + memcpy(t, psk, psk_len); + + s->session->master_key_length = + s->method->ssl3_enc->generate_master_secret(s, + s->session->master_key, + pre_ms, pre_ms_len); + s2n(identity_len, p); + memcpy(p, identity, identity_len); + n = 2 + identity_len; + } + + if (s->session->psk_identity != NULL) + OPENSSL_free(s->session->psk_identity); + s->session->psk_identity = BUF_strdup(identity); + if (s->session->psk_identity == NULL) + { + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, + ERR_R_MALLOC_FAILURE); + goto psk_err; + } + psk_err = 0; + psk_err: + OPENSSL_cleanse(identity, PSK_MAX_IDENTITY_LEN); + OPENSSL_cleanse(pre_ms, sizeof(pre_ms)); + if (psk_err != 0) + { + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); + goto err; + } + } +#endif /* Fool emacs indentation */ if (0) {} #ifndef OPENSSL_NO_RSA @@ -2580,14 +2673,19 @@ int ssl3_send_client_key_exchange(SSL *s) /* perhaps clean things up a bit EAY EAY EAY EAY*/ } #endif - -#ifndef OPENSSL_NO_ECDH +#ifndef OPENSSL_NO_ECDH else if (alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe)) { const EC_GROUP *srvr_group = NULL; EC_KEY *tkey; int ecdh_clnt_cert = 0; int field_size = 0; +#ifndef OPENSSL_NO_PSK + unsigned char *pre_ms; + unsigned char *t; + unsigned int pre_ms_len; + unsigned int i; +#endif /* Did we send out the client's * ECDH share for use in premaster @@ -2708,15 +2806,41 @@ int ssl3_send_client_key_exchange(SSL *s) goto err; } - /* generate master key from the result */ - s->session->master_key_length = s->method->ssl3_enc \ - -> generate_master_secret(s, - s->session->master_key, - p, n); - +#ifndef OPENSSL_NO_PSK + /* ECDHE PSK ciphersuites from RFC 5489 */ + if ((alg_a & SSL_aPSK) && psk_len != 0) + { + pre_ms_len = 2+psk_len+2+n; + pre_ms = OPENSSL_malloc(pre_ms_len); + if (pre_ms == NULL) + { + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, + ERR_R_MALLOC_FAILURE); + goto err; + } + memset(pre_ms, 0, pre_ms_len); + t = pre_ms; + s2n(psk_len, t); + memcpy(t, psk, psk_len); + t += psk_len; + s2n(n, t); + memcpy(t, p, n); + s->session->master_key_length = s->method->ssl3_enc \ + -> generate_master_secret(s, + s->session->master_key, pre_ms, pre_ms_len); + OPENSSL_cleanse(pre_ms, pre_ms_len); + OPENSSL_free(pre_ms); + } +#endif /* OPENSSL_NO_PSK */ + if (!(alg_a & SSL_aPSK)) + { + /* generate master key from the result */ + s->session->master_key_length = s->method->ssl3_enc \ + -> generate_master_secret(s, + s->session->master_key, p, n); + } memset(p, 0, n); /* clean up */ - - if (ecdh_clnt_cert) + if (ecdh_clnt_cert) { /* Send empty client key exch message */ n = 0; @@ -2744,29 +2868,42 @@ int ssl3_send_client_key_exchange(SSL *s) } /* Encode the public key */ - n = EC_POINT_point2oct(srvr_group, - EC_KEY_get0_public_key(clnt_ecdh), - POINT_CONVERSION_UNCOMPRESSED, + encoded_pt_len = EC_POINT_point2oct(srvr_group, + EC_KEY_get0_public_key(clnt_ecdh), + POINT_CONVERSION_UNCOMPRESSED, encodedPoint, encoded_pt_len, bn_ctx); + + n = 0; +#ifndef OPENSSL_NO_PSK + if ((alg_a & SSL_aPSK) && psk_len != 0) + { + i = strlen(s->session->psk_identity); + s2n(i, p); + memcpy(p, s->session->psk_identity, i); + p += i; + n = i + 2; + } +#endif - *p = n; /* length of encoded point */ + *p = encoded_pt_len; /* length of encoded point */ /* Encoded point will be copied here */ - p += 1; + p += 1; + n += 1; /* copy the point */ - memcpy((unsigned char *)p, encodedPoint, n); + memcpy((unsigned char *)p, encodedPoint, encoded_pt_len); /* increment n to account for length field */ - n += 1; + n += encoded_pt_len; } /* Free allocated memory */ BN_CTX_free(bn_ctx); if (encodedPoint != NULL) OPENSSL_free(encodedPoint); - if (clnt_ecdh != NULL) + if (clnt_ecdh != NULL) EC_KEY_free(clnt_ecdh); EVP_PKEY_free(srvr_pub_pkey); } #endif /* !OPENSSL_NO_ECDH */ - else if (alg_k & SSL_kGOST) + else if (alg_k & SSL_kGOST) { /* GOST key exchange message creation */ EVP_PKEY_CTX *pkey_ctx; @@ -2889,89 +3026,7 @@ int ssl3_send_client_key_exchange(SSL *s) } } #endif -#ifndef OPENSSL_NO_PSK - else if (alg_k & SSL_kPSK) - { - char identity[PSK_MAX_IDENTITY_LEN]; - unsigned char *t = NULL; - unsigned char psk_or_pre_ms[PSK_MAX_PSK_LEN*2+4]; - unsigned int pre_ms_len = 0, psk_len = 0; - int psk_err = 1; - - n = 0; - if (s->psk_client_callback == NULL) - { - SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, - SSL_R_PSK_NO_CLIENT_CB); - goto err; - } - - psk_len = s->psk_client_callback(s, s->ctx->psk_identity_hint, - identity, PSK_MAX_IDENTITY_LEN, - psk_or_pre_ms, sizeof(psk_or_pre_ms)); - if (psk_len > PSK_MAX_PSK_LEN) - { - SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, - ERR_R_INTERNAL_ERROR); - goto psk_err; - } - else if (psk_len == 0) - { - SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, - SSL_R_PSK_IDENTITY_NOT_FOUND); - goto psk_err; - } - - /* create PSK pre_master_secret */ - pre_ms_len = 2+psk_len+2+psk_len; - t = psk_or_pre_ms; - memmove(psk_or_pre_ms+psk_len+4, psk_or_pre_ms, psk_len); - s2n(psk_len, t); - memset(t, 0, psk_len); - t+=psk_len; - s2n(psk_len, t); - - if (s->session->psk_identity_hint != NULL) - OPENSSL_free(s->session->psk_identity_hint); - s->session->psk_identity_hint = BUF_strdup(s->ctx->psk_identity_hint); - if (s->ctx->psk_identity_hint != NULL && - s->session->psk_identity_hint == NULL) - { - SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, - ERR_R_MALLOC_FAILURE); - goto psk_err; - } - - if (s->session->psk_identity != NULL) - OPENSSL_free(s->session->psk_identity); - s->session->psk_identity = BUF_strdup(identity); - if (s->session->psk_identity == NULL) - { - SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, - ERR_R_MALLOC_FAILURE); - goto psk_err; - } - - s->session->master_key_length = - s->method->ssl3_enc->generate_master_secret(s, - s->session->master_key, - psk_or_pre_ms, pre_ms_len); - n = strlen(identity); - s2n(n, p); - memcpy(p, identity, n); - n+=2; - psk_err = 0; - psk_err: - OPENSSL_cleanse(identity, PSK_MAX_IDENTITY_LEN); - OPENSSL_cleanse(psk_or_pre_ms, sizeof(psk_or_pre_ms)); - if (psk_err != 0) - { - ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); - goto err; - } - } -#endif - else + else if (!(alg_k & SSL_kPSK)) { ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); @@ -3276,7 +3331,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_aDH|SSL_aNULL|SSL_aKRB5)) || ((alg_a & SSL_aPSK) && !(alg_k & SSL_kRSA))) return(1); sc=s->session->sess_cert; diff --git a/main/openssl/ssl/s3_lib.c b/main/openssl/ssl/s3_lib.c index f7a5c6f0..f84da7f5 100644 --- a/main/openssl/ssl/s3_lib.c +++ b/main/openssl/ssl/s3_lib.c @@ -2826,6 +2826,42 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={ 256, }, +#ifndef OPENSSL_NO_PSK + /* ECDH PSK ciphersuites from RFC 5489 */ + + /* Cipher C037 */ + { + 1, + TLS1_TXT_ECDHE_PSK_WITH_AES_128_CBC_SHA256, + TLS1_CK_ECDHE_PSK_WITH_AES_128_CBC_SHA256, + SSL_kEECDH, + SSL_aPSK, + SSL_AES128, + SSL_SHA256, + SSL_TLSV1, + SSL_NOT_EXP|SSL_HIGH, + SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF_SHA256, + 128, + 128, + }, + + /* Cipher C038 */ + { + 1, + TLS1_TXT_ECDHE_PSK_WITH_AES_256_CBC_SHA384, + TLS1_CK_ECDHE_PSK_WITH_AES_256_CBC_SHA384, + SSL_kEECDH, + SSL_aPSK, + SSL_AES256, + SSL_SHA384, + SSL_TLSV1, + SSL_NOT_EXP|SSL_HIGH, + SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF_SHA384, + 256, + 256, + }, +#endif /* OPENSSL_NO_PSK */ + #endif /* OPENSSL_NO_ECDH */ @@ -3911,7 +3947,7 @@ SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt, #endif /* OPENSSL_NO_KRB5 */ #ifndef OPENSSL_NO_PSK /* with PSK there must be server callback set */ - if ((alg_k & SSL_kPSK) && s->psk_server_callback == NULL) + if ((alg_a & SSL_aPSK) && s->psk_server_callback == NULL) continue; #endif /* OPENSSL_NO_PSK */ diff --git a/main/openssl/ssl/s3_srvr.c b/main/openssl/ssl/s3_srvr.c index 8692f149..0ee781f1 100644 --- a/main/openssl/ssl/s3_srvr.c +++ b/main/openssl/ssl/s3_srvr.c @@ -217,6 +217,7 @@ int ssl3_accept(SSL *s) { BUF_MEM *buf; unsigned long alg_k,Time=(unsigned long)time(NULL); + unsigned long alg_a; void (*cb)(const SSL *ssl,int type,int val)=NULL; int ret= -1; int new_state,state,skip=0; @@ -412,9 +413,11 @@ int ssl3_accept(SSL *s) case SSL3_ST_SW_CERT_A: case SSL3_ST_SW_CERT_B: /* Check if it is anon DH or anon ECDH, */ - /* normal PSK or KRB5 or SRP */ + /* non-RSA PSK or KRB5 or SRP */ if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) - && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK) + /* Among PSK ciphersuites only RSA_PSK uses server certificate */ + && !(s->s3->tmp.new_cipher->algorithm_auth & SSL_aPSK && + !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kRSA)) && !(s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5)) { ret=ssl3_send_server_certificate(s); @@ -443,6 +446,7 @@ int ssl3_accept(SSL *s) case SSL3_ST_SW_KEY_EXCH_A: case SSL3_ST_SW_KEY_EXCH_B: alg_k = s->s3->tmp.new_cipher->algorithm_mkey; + alg_a = s->s3->tmp.new_cipher->algorithm_auth; /* clear this, it may get reset by * send_server_key_exchange */ @@ -472,10 +476,12 @@ int ssl3_accept(SSL *s) * public key for key exchange. */ if (s->s3->tmp.use_rsa_tmp - /* PSK: send ServerKeyExchange if PSK identity - * hint if provided */ + /* PSK: send ServerKeyExchange if either: + * - PSK identity hint is provided, or + * - the key exchange is kEECDH. + */ #ifndef OPENSSL_NO_PSK - || ((alg_k & SSL_kPSK) && s->ctx->psk_identity_hint) + || ((alg_a & SSL_aPSK) && ((alg_k & SSL_kEECDH) || s->session->psk_identity_hint)) #endif #ifndef OPENSSL_NO_SRP /* SRP: send ServerKeyExchange */ @@ -1589,11 +1595,16 @@ int ssl3_send_server_key_exchange(SSL *s) int curve_id = 0; BN_CTX *bn_ctx = NULL; #endif +#ifndef OPENSSL_NO_PSK + const char* psk_identity_hint; + size_t psk_identity_hint_len; +#endif EVP_PKEY *pkey; const EVP_MD *md = NULL; unsigned char *p,*d; int al,i; - unsigned long type; + unsigned long alg_k; + unsigned long alg_a; int n; CERT *cert; BIGNUM *r[4]; @@ -1604,15 +1615,28 @@ int ssl3_send_server_key_exchange(SSL *s) EVP_MD_CTX_init(&md_ctx); if (s->state == SSL3_ST_SW_KEY_EXCH_A) { - type=s->s3->tmp.new_cipher->algorithm_mkey; + alg_k=s->s3->tmp.new_cipher->algorithm_mkey; + alg_a=s->s3->tmp.new_cipher->algorithm_auth; cert=s->cert; buf=s->init_buf; r[0]=r[1]=r[2]=r[3]=NULL; n=0; +#ifndef OPENSSL_NO_PSK + if (alg_a & SSL_aPSK) + { + /* size for PSK identity hint */ + psk_identity_hint = s->session->psk_identity_hint; + if (psk_identity_hint) + psk_identity_hint_len = strlen(psk_identity_hint); + else + psk_identity_hint_len = 0; + n+=2+psk_identity_hint_len; + } +#endif /* !OPENSSL_NO_PSK */ #ifndef OPENSSL_NO_RSA - if (type & SSL_kRSA) + if (alg_k & SSL_kRSA) { rsa=cert->rsa_tmp; if ((rsa == NULL) && (s->cert->rsa_tmp_cb != NULL)) @@ -1639,10 +1663,9 @@ int ssl3_send_server_key_exchange(SSL *s) r[1]=rsa->e; s->s3->tmp.use_rsa_tmp=1; } - else #endif #ifndef OPENSSL_NO_DH - if (type & SSL_kEDH) + else if (alg_k & SSL_kEDH) { dhp=cert->dh_tmp; if ((dhp == NULL) && (s->cert->dh_tmp_cb != NULL)) @@ -1695,10 +1718,9 @@ int ssl3_send_server_key_exchange(SSL *s) r[1]=dh->g; r[2]=dh->pub_key; } - else #endif #ifndef OPENSSL_NO_ECDH - if (type & SSL_kEECDH) + else if (alg_k & SSL_kEECDH) { const EC_GROUP *group; @@ -1811,7 +1833,7 @@ int ssl3_send_server_key_exchange(SSL *s) * to encode the entire ServerECDHParams * structure. */ - n = 4 + encodedlen; + n += 4 + encodedlen; /* We'll generate the serverKeyExchange message * explicitly so we can set these to NULLs @@ -1821,18 +1843,9 @@ int ssl3_send_server_key_exchange(SSL *s) r[2]=NULL; r[3]=NULL; } - else #endif /* !OPENSSL_NO_ECDH */ -#ifndef OPENSSL_NO_PSK - if (type & SSL_kPSK) - { - /* reserve size for record length and PSK identity hint*/ - n+=2+strlen(s->ctx->psk_identity_hint); - } - else -#endif /* !OPENSSL_NO_PSK */ #ifndef OPENSSL_NO_SRP - if (type & SSL_kSRP) + else if (alg_k & SSL_kSRP) { if ((s->srp_ctx.N == NULL) || (s->srp_ctx.g == NULL) || @@ -1847,8 +1860,8 @@ int ssl3_send_server_key_exchange(SSL *s) r[2]=s->srp_ctx.s; r[3]=s->srp_ctx.B; } - else #endif + else if (!(alg_k & SSL_kPSK)) { al=SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE); @@ -1858,15 +1871,16 @@ int ssl3_send_server_key_exchange(SSL *s) { nr[i]=BN_num_bytes(r[i]); #ifndef OPENSSL_NO_SRP - if ((i == 2) && (type & SSL_kSRP)) + if ((i == 2) && (alg_k & SSL_kSRP)) n+=1+nr[i]; else #endif n+=2+nr[i]; } - if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) - && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) + if (!(alg_a & SSL_aNULL) + /* Among PSK ciphersuites only RSA uses a certificate */ + && !((alg_a & SSL_aPSK) && !(alg_k & SSL_kRSA))) { if ((pkey=ssl_get_sign_pkey(s,s->s3->tmp.new_cipher,&md)) == NULL) @@ -1893,7 +1907,7 @@ int ssl3_send_server_key_exchange(SSL *s) for (i=0; i < 4 && r[i] != NULL; i++) { #ifndef OPENSSL_NO_SRP - if ((i == 2) && (type & SSL_kSRP)) + if ((i == 2) && (alg_k & SSL_kSRP)) { *p = nr[i]; p++; @@ -1905,8 +1919,24 @@ int ssl3_send_server_key_exchange(SSL *s) p+=nr[i]; } +/* Note: ECDHE PSK ciphersuites use SSL_kEECDH and SSL_aPSK. + * When one of them is used, the server key exchange record needs to have both + * the psk_identity_hint and the ServerECDHParams. */ +#ifndef OPENSSL_NO_PSK + if (alg_a & SSL_aPSK) + { + /* copy PSK identity hint (if provided) */ + s2n(psk_identity_hint_len, p); + if (psk_identity_hint_len > 0) + { + memcpy(p, psk_identity_hint, psk_identity_hint_len); + p+=psk_identity_hint_len; + } + } +#endif /* OPENSSL_NO_PSK */ + #ifndef OPENSSL_NO_ECDH - if (type & SSL_kEECDH) + if (alg_k & SSL_kEECDH) { /* XXX: For now, we only support named (not generic) curves. * In this situation, the serverKeyExchange message has: @@ -1929,17 +1959,7 @@ int ssl3_send_server_key_exchange(SSL *s) encodedPoint = NULL; p += encodedlen; } -#endif - -#ifndef OPENSSL_NO_PSK - if (type & SSL_kPSK) - { - /* copy PSK identity hint */ - s2n(strlen(s->ctx->psk_identity_hint), p); - strncpy((char *)p, s->ctx->psk_identity_hint, strlen(s->ctx->psk_identity_hint)); - p+=strlen(s->ctx->psk_identity_hint); - } -#endif +#endif /* OPENSSL_NO_ECDH */ /* not anonymous */ if (pkey != NULL) @@ -1976,7 +1996,7 @@ int ssl3_send_server_key_exchange(SSL *s) n+=u+2; } else -#endif +#endif /* OPENSSL_NO_RSA */ if (md) { /* For TLS1.2 and later send signature @@ -2145,6 +2165,7 @@ int ssl3_get_client_key_exchange(SSL *s) int i,al,ok; long n; unsigned long alg_k; + unsigned long alg_a; unsigned char *p; #ifndef OPENSSL_NO_RSA RSA *rsa=NULL; @@ -2162,7 +2183,11 @@ int ssl3_get_client_key_exchange(SSL *s) EC_KEY *srvr_ecdh = NULL; EVP_PKEY *clnt_pub_pkey = NULL; EC_POINT *clnt_ecpoint = NULL; - BN_CTX *bn_ctx = NULL; + BN_CTX *bn_ctx = NULL; +#ifndef OPENSSL_NO_PSK + unsigned int psk_len = 0; + unsigned char psk[PSK_MAX_PSK_LEN]; +#endif /* OPENSSL_NO_PSK */ #endif n=s->method->ssl_get_message(s, @@ -2176,7 +2201,95 @@ int ssl3_get_client_key_exchange(SSL *s) p=(unsigned char *)s->init_msg; alg_k=s->s3->tmp.new_cipher->algorithm_mkey; + alg_a=s->s3->tmp.new_cipher->algorithm_auth; +#ifndef OPENSSL_NO_PSK + if (alg_a & SSL_aPSK) + { + unsigned char *t = NULL; + unsigned char pre_ms[PSK_MAX_PSK_LEN*2+4]; + unsigned int pre_ms_len = 0; + int psk_err = 1; + char tmp_id[PSK_MAX_IDENTITY_LEN+1]; + + al=SSL_AD_HANDSHAKE_FAILURE; + + n2s(p, i); + if (n != i+2 && !(alg_k & SSL_kEECDH)) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + SSL_R_LENGTH_MISMATCH); + goto psk_err; + } + if (i > PSK_MAX_IDENTITY_LEN) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + SSL_R_DATA_LENGTH_TOO_LONG); + goto psk_err; + } + if (s->psk_server_callback == NULL) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + SSL_R_PSK_NO_SERVER_CB); + goto psk_err; + } + + /* Create guaranteed NUL-terminated identity + * string for the callback */ + memcpy(tmp_id, p, i); + memset(tmp_id+i, 0, PSK_MAX_IDENTITY_LEN+1-i); + psk_len = s->psk_server_callback(s, tmp_id, psk, sizeof(psk)); + + if (psk_len > PSK_MAX_PSK_LEN) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + ERR_R_INTERNAL_ERROR); + goto psk_err; + } + else if (psk_len == 0) + { + /* PSK related to the given identity not found */ + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + SSL_R_PSK_IDENTITY_NOT_FOUND); + al=SSL_AD_UNKNOWN_PSK_IDENTITY; + goto psk_err; + } + if (!(alg_k & SSL_kEECDH)) + { + /* Create the shared secret now if we're not using ECDHE-PSK.*/ + pre_ms_len=2+psk_len+2+psk_len; + t = pre_ms; + s2n(psk_len, t); + memset(t, 0, psk_len); + t+=psk_len; + s2n(psk_len, t); + memcpy(t, psk, psk_len); + + s->session->master_key_length= + s->method->ssl3_enc->generate_master_secret(s, + s->session->master_key, pre_ms, pre_ms_len); + } + if (s->session->psk_identity != NULL) + OPENSSL_free(s->session->psk_identity); + s->session->psk_identity = BUF_strdup(tmp_id); + OPENSSL_cleanse(tmp_id, PSK_MAX_IDENTITY_LEN+1); + if (s->session->psk_identity == NULL) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + ERR_R_MALLOC_FAILURE); + goto psk_err; + } + + p += i; + n -= (i + 2); + psk_err = 0; + psk_err: + OPENSSL_cleanse(pre_ms, sizeof(pre_ms)); + if (psk_err != 0) + goto f_err; + } +#endif /* OPENSSL_NO_PSK */ + if (0) {} #ifndef OPENSSL_NO_RSA if (alg_k & SSL_kRSA) { @@ -2281,10 +2394,9 @@ int ssl3_get_client_key_exchange(SSL *s) p,i); OPENSSL_cleanse(p,i); } - else #endif #ifndef OPENSSL_NO_DH - if (alg_k & (SSL_kEDH|SSL_kDHr|SSL_kDHd)) + else if (alg_k & (SSL_kEDH|SSL_kDHr|SSL_kDHd)) { n2s(p,i); if (n != i+2) @@ -2345,10 +2457,9 @@ int ssl3_get_client_key_exchange(SSL *s) s->session->master_key,p,i); OPENSSL_cleanse(p,i); } - else #endif #ifndef OPENSSL_NO_KRB5 - if (alg_k & SSL_kKRB5) + else if (alg_k & SSL_kKRB5) { krb5_error_code krb5rc; krb5_data enc_ticket; @@ -2537,17 +2648,20 @@ int ssl3_get_client_key_exchange(SSL *s) ** if (s->kssl_ctx) s->kssl_ctx = NULL; */ } - else #endif /* OPENSSL_NO_KRB5 */ - #ifndef OPENSSL_NO_ECDH - if (alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe)) + else if (alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe)) { int ret = 1; int field_size = 0; const EC_KEY *tkey; const EC_GROUP *group; const BIGNUM *priv_key; +#ifndef OPENSSL_NO_PSK + unsigned char *pre_ms; + unsigned int pre_ms_len; + unsigned char *t; +#endif /* OPENSSL_NO_PSK */ /* initialize structures for server's ECDH key pair */ if ((srvr_ecdh = EC_KEY_new()) == NULL) @@ -2643,7 +2757,7 @@ int ssl3_get_client_key_exchange(SSL *s) } /* Get encoded point length */ - i = *p; + i = *p; p += 1; if (n != 1 + i) { @@ -2685,223 +2799,155 @@ int ssl3_get_client_key_exchange(SSL *s) EC_KEY_free(srvr_ecdh); BN_CTX_free(bn_ctx); EC_KEY_free(s->s3->tmp.ecdh); - s->s3->tmp.ecdh = NULL; + s->s3->tmp.ecdh = NULL; - /* Compute the master secret */ - s->session->master_key_length = s->method->ssl3_enc-> \ - generate_master_secret(s, s->session->master_key, p, i); - - OPENSSL_cleanse(p, i); - return (ret); - } - else -#endif #ifndef OPENSSL_NO_PSK - if (alg_k & SSL_kPSK) + /* ECDHE PSK ciphersuites from RFC 5489 */ + if ((alg_a & SSL_aPSK) && psk_len != 0) { - unsigned char *t = NULL; - unsigned char psk_or_pre_ms[PSK_MAX_PSK_LEN*2+4]; - unsigned int pre_ms_len = 0, psk_len = 0; - int psk_err = 1; - char tmp_id[PSK_MAX_IDENTITY_LEN+1]; - - al=SSL_AD_HANDSHAKE_FAILURE; - - n2s(p,i); - if (n != i+2) - { - SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, - SSL_R_LENGTH_MISMATCH); - goto psk_err; - } - if (i > PSK_MAX_IDENTITY_LEN) - { - SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, - SSL_R_DATA_LENGTH_TOO_LONG); - goto psk_err; - } - if (s->psk_server_callback == NULL) - { - SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, - SSL_R_PSK_NO_SERVER_CB); - goto psk_err; - } - - /* Create guaranteed NULL-terminated identity - * string for the callback */ - memcpy(tmp_id, p, i); - memset(tmp_id+i, 0, PSK_MAX_IDENTITY_LEN+1-i); - psk_len = s->psk_server_callback(s, tmp_id, - psk_or_pre_ms, sizeof(psk_or_pre_ms)); - OPENSSL_cleanse(tmp_id, PSK_MAX_IDENTITY_LEN+1); - - if (psk_len > PSK_MAX_PSK_LEN) - { - SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, - ERR_R_INTERNAL_ERROR); - goto psk_err; - } - else if (psk_len == 0) - { - /* PSK related to the given identity not found */ - SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, - SSL_R_PSK_IDENTITY_NOT_FOUND); - al=SSL_AD_UNKNOWN_PSK_IDENTITY; - goto psk_err; - } - - /* create PSK pre_master_secret */ - pre_ms_len=2+psk_len+2+psk_len; - t = psk_or_pre_ms; - memmove(psk_or_pre_ms+psk_len+4, psk_or_pre_ms, psk_len); - s2n(psk_len, t); - memset(t, 0, psk_len); - t+=psk_len; - s2n(psk_len, t); - - if (s->session->psk_identity != NULL) - OPENSSL_free(s->session->psk_identity); - s->session->psk_identity = BUF_strdup((char *)p); - if (s->session->psk_identity == NULL) - { - SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, - ERR_R_MALLOC_FAILURE); - goto psk_err; - } - - if (s->session->psk_identity_hint != NULL) - OPENSSL_free(s->session->psk_identity_hint); - s->session->psk_identity_hint = BUF_strdup(s->ctx->psk_identity_hint); - if (s->ctx->psk_identity_hint != NULL && - s->session->psk_identity_hint == NULL) + pre_ms_len = 2+psk_len+2+i; + pre_ms = OPENSSL_malloc(pre_ms_len); + if (pre_ms == NULL) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE); - goto psk_err; + goto err; } - - s->session->master_key_length= - s->method->ssl3_enc->generate_master_secret(s, - s->session->master_key, psk_or_pre_ms, pre_ms_len); - psk_err = 0; - psk_err: - OPENSSL_cleanse(psk_or_pre_ms, sizeof(psk_or_pre_ms)); - if (psk_err != 0) - goto f_err; + memset(pre_ms, 0, pre_ms_len); + t = pre_ms; + s2n(psk_len, t); + memcpy(t, psk, psk_len); + t += psk_len; + s2n(i, t); + memcpy(t, p, i); + s->session->master_key_length = s->method->ssl3_enc \ + -> generate_master_secret(s, + s->session->master_key, pre_ms, pre_ms_len); + OPENSSL_cleanse(pre_ms, pre_ms_len); + OPENSSL_free(pre_ms); } - else +#endif /* OPENSSL_NO_PSK */ + if (!(alg_a & SSL_aPSK)) + { + /* Compute the master secret */ + s->session->master_key_length = s->method->ssl3_enc \ + -> generate_master_secret(s, + s->session->master_key, p, i); + } + + OPENSSL_cleanse(p, i); + } #endif #ifndef OPENSSL_NO_SRP - if (alg_k & SSL_kSRP) + else if (alg_k & SSL_kSRP) + { + int param_len; + + n2s(p,i); + param_len=i+2; + if (param_len > n) + { + al=SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BAD_SRP_A_LENGTH); + goto f_err; + } + if (!(s->srp_ctx.A=BN_bin2bn(p,i,NULL))) { - int param_len; + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,ERR_R_BN_LIB); + goto err; + } + if (s->session->srp_username != NULL) + OPENSSL_free(s->session->srp_username); + s->session->srp_username = BUF_strdup(s->srp_ctx.login); + if (s->session->srp_username == NULL) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + ERR_R_MALLOC_FAILURE); + goto err; + } - n2s(p,i); - param_len=i+2; - if (param_len > n) - { - al=SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BAD_SRP_A_LENGTH); - goto f_err; - } - if (!(s->srp_ctx.A=BN_bin2bn(p,i,NULL))) - { - SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,ERR_R_BN_LIB); - goto err; - } - if (s->session->srp_username != NULL) - OPENSSL_free(s->session->srp_username); - s->session->srp_username = BUF_strdup(s->srp_ctx.login); - if (s->session->srp_username == NULL) - { - SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, - ERR_R_MALLOC_FAILURE); - goto err; - } + if ((s->session->master_key_length = SRP_generate_server_master_secret(s,s->session->master_key))<0) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR); + goto err; + } - if ((s->session->master_key_length = SRP_generate_server_master_secret(s,s->session->master_key))<0) - { - SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR); - goto err; - } + p+=i; + } +#endif /* OPENSSL_NO_SRP */ + else if (alg_k & SSL_kGOST) + { + int ret = 0; + EVP_PKEY_CTX *pkey_ctx; + EVP_PKEY *client_pub_pkey = NULL, *pk = NULL; + unsigned char premaster_secret[32], *start; + size_t outlen=32, inlen; + unsigned long alg_a; + + /* Get our certificate private key*/ + alg_a = s->s3->tmp.new_cipher->algorithm_auth; + if (alg_a & SSL_aGOST94) + pk = s->cert->pkeys[SSL_PKEY_GOST94].privatekey; + else if (alg_a & SSL_aGOST01) + pk = s->cert->pkeys[SSL_PKEY_GOST01].privatekey; - p+=i; + pkey_ctx = EVP_PKEY_CTX_new(pk,NULL); + EVP_PKEY_decrypt_init(pkey_ctx); + /* If client certificate is present and is of the same type, maybe + * use it for key exchange. Don't mind errors from + * EVP_PKEY_derive_set_peer, because it is completely valid to use + * a client certificate for authorization only. */ + client_pub_pkey = X509_get_pubkey(s->session->peer); + if (client_pub_pkey) + { + if (EVP_PKEY_derive_set_peer(pkey_ctx, client_pub_pkey) <= 0) + ERR_clear_error(); + } + /* Decrypt session key */ + if ((*p!=( V_ASN1_SEQUENCE| V_ASN1_CONSTRUCTED))) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_DECRYPTION_FAILED); + goto gerr; + } + if (p[1] == 0x81) + { + start = p+3; + inlen = p[2]; + } + else if (p[1] < 0x80) + { + start = p+2; + inlen = p[1]; } else -#endif /* OPENSSL_NO_SRP */ - if (alg_k & SSL_kGOST) { - int ret = 0; - EVP_PKEY_CTX *pkey_ctx; - EVP_PKEY *client_pub_pkey = NULL, *pk = NULL; - unsigned char premaster_secret[32], *start; - size_t outlen=32, inlen; - unsigned long alg_a; - - /* Get our certificate private key*/ - alg_a = s->s3->tmp.new_cipher->algorithm_auth; - if (alg_a & SSL_aGOST94) - pk = s->cert->pkeys[SSL_PKEY_GOST94].privatekey; - else if (alg_a & SSL_aGOST01) - pk = s->cert->pkeys[SSL_PKEY_GOST01].privatekey; - - pkey_ctx = EVP_PKEY_CTX_new(pk,NULL); - EVP_PKEY_decrypt_init(pkey_ctx); - /* If client certificate is present and is of the same type, maybe - * use it for key exchange. Don't mind errors from - * EVP_PKEY_derive_set_peer, because it is completely valid to use - * a client certificate for authorization only. */ - client_pub_pkey = X509_get_pubkey(s->session->peer); - if (client_pub_pkey) - { - if (EVP_PKEY_derive_set_peer(pkey_ctx, client_pub_pkey) <= 0) - ERR_clear_error(); - } - /* Decrypt session key */ - if ((*p!=( V_ASN1_SEQUENCE| V_ASN1_CONSTRUCTED))) - { - SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_DECRYPTION_FAILED); - goto gerr; - } - if (p[1] == 0x81) - { - start = p+3; - inlen = p[2]; - } - else if (p[1] < 0x80) - { - start = p+2; - inlen = p[1]; - } - else - { - SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_DECRYPTION_FAILED); - goto gerr; - } - if (EVP_PKEY_decrypt(pkey_ctx,premaster_secret,&outlen,start,inlen) <=0) + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_DECRYPTION_FAILED); + goto gerr; + } + if (EVP_PKEY_decrypt(pkey_ctx,premaster_secret,&outlen,start,inlen) <=0) - { - SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_DECRYPTION_FAILED); - goto gerr; - } - /* Generate master secret */ - s->session->master_key_length= - s->method->ssl3_enc->generate_master_secret(s, - s->session->master_key,premaster_secret,32); - /* Check if pubkey from client certificate was used */ - if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 2, NULL) > 0) - ret = 2; - else - ret = 1; - gerr: - EVP_PKEY_free(client_pub_pkey); - EVP_PKEY_CTX_free(pkey_ctx); - if (ret) - return ret; - else - goto err; + { + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_DECRYPTION_FAILED); + goto gerr; } + /* Generate master secret */ + s->session->master_key_length= + s->method->ssl3_enc->generate_master_secret(s, + s->session->master_key,premaster_secret,32); + /* Check if pubkey from client certificate was used */ + if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 2, NULL) > 0) + ret = 2; + else + ret = 1; + gerr: + EVP_PKEY_free(client_pub_pkey); + EVP_PKEY_CTX_free(pkey_ctx); + if (ret) + return ret; else + goto err; + } + else if (!(alg_k & SSL_kPSK)) { al=SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, diff --git a/main/openssl/ssl/ssl.h b/main/openssl/ssl/ssl.h index 40c4d9cf..57335a98 100644 --- a/main/openssl/ssl/ssl.h +++ b/main/openssl/ssl/ssl.h @@ -1315,6 +1315,10 @@ struct ssl_st #endif /* OPENSSL_NO_KRB5 */ #ifndef OPENSSL_NO_PSK + /* PSK identity hint is stored here only to enable setting a hint on an SSL object before an + * SSL_SESSION is associated with it. Once an SSL_SESSION is associated with this SSL object, + * the psk_identity_hint from the session takes precedence over this one. */ + char *psk_identity_hint; unsigned int (*psk_client_callback)(SSL *ssl, const char *hint, char *identity, unsigned int max_identity_len, unsigned char *psk, unsigned int max_psk_len); diff --git a/main/openssl/ssl/ssl_lib.c b/main/openssl/ssl/ssl_lib.c index 74523862..8d2c3a76 100644 --- a/main/openssl/ssl/ssl_lib.c +++ b/main/openssl/ssl/ssl_lib.c @@ -388,6 +388,13 @@ SSL *SSL_new(SSL_CTX *ctx) CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL, s, &s->ex_data); #ifndef OPENSSL_NO_PSK + s->psk_identity_hint = NULL; + if (ctx->psk_identity_hint) + { + s->psk_identity_hint = BUF_strdup(ctx->psk_identity_hint); + if (s->psk_identity_hint == NULL) + goto err; + } s->psk_client_callback=ctx->psk_client_callback; s->psk_server_callback=ctx->psk_server_callback; #endif @@ -596,6 +603,11 @@ void SSL_free(SSL *s) OPENSSL_free(s->alpn_client_proto_list); #endif +#ifndef OPENSSL_NO_PSK + if (s->psk_identity_hint) + OPENSSL_free(s->psk_identity_hint); +#endif + if (s->client_CA != NULL) sk_X509_NAME_pop_free(s->client_CA,X509_NAME_free); @@ -1440,7 +1452,7 @@ int ssl_cipher_list_to_bytes(SSL *s,STACK_OF(SSL_CIPHER) *sk,unsigned char *p, #endif /* OPENSSL_NO_KRB5 */ #ifndef OPENSSL_NO_PSK /* with PSK there must be client callback set */ - if (((c->algorithm_mkey & SSL_kPSK) || (c->algorithm_auth & SSL_aPSK)) && + if ((c->algorithm_auth & SSL_aPSK) && s->psk_client_callback == NULL) continue; #endif /* OPENSSL_NO_PSK */ @@ -3303,32 +3315,54 @@ int SSL_use_psk_identity_hint(SSL *s, const char *identity_hint) if (s == NULL) return 0; - if (s->session == NULL) - return 1; /* session not created yet, ignored */ - if (identity_hint != NULL && strlen(identity_hint) > PSK_MAX_IDENTITY_LEN) { SSLerr(SSL_F_SSL_USE_PSK_IDENTITY_HINT, SSL_R_DATA_LENGTH_TOO_LONG); return 0; } - if (s->session->psk_identity_hint != NULL) + + /* Clear hint in SSL and associated SSL_SESSION (if any). */ + if (s->psk_identity_hint != NULL) + { + OPENSSL_free(s->psk_identity_hint); + s->psk_identity_hint = NULL; + } + if (s->session != NULL && s->session->psk_identity_hint != NULL) + { OPENSSL_free(s->session->psk_identity_hint); + s->session->psk_identity_hint = NULL; + } + if (identity_hint != NULL) { - s->session->psk_identity_hint = BUF_strdup(identity_hint); - if (s->session->psk_identity_hint == NULL) - return 0; + /* The hint is stored in SSL and SSL_SESSION with the one in + * SSL_SESSION taking precedence. Thus, if SSL_SESSION is avaiable, + * we store the hint there, otherwise we store it in SSL. */ + if (s->session != NULL) + { + s->session->psk_identity_hint = BUF_strdup(identity_hint); + if (s->session->psk_identity_hint == NULL) + return 0; + } + else + { + s->psk_identity_hint = BUF_strdup(identity_hint); + if (s->psk_identity_hint == NULL) + return 0; + } } - else - s->session->psk_identity_hint = NULL; return 1; } const char *SSL_get_psk_identity_hint(const SSL *s) { - if (s == NULL || s->session == NULL) + if (s == NULL) return NULL; - return(s->session->psk_identity_hint); + /* The hint is stored in SSL and SSL_SESSION with the one in SSL_SESSION + * taking precedence. */ + if (s->session != NULL) + return(s->session->psk_identity_hint); + return(s->psk_identity_hint); } const char *SSL_get_psk_identity(const SSL *s) diff --git a/main/openssl/ssl/ssl_sess.c b/main/openssl/ssl/ssl_sess.c index 920b763e..ec088404 100644 --- a/main/openssl/ssl/ssl_sess.c +++ b/main/openssl/ssl/ssl_sess.c @@ -427,6 +427,18 @@ int ssl_get_new_session(SSL *s, int session) } #endif #endif +#ifndef OPENSSL_NO_PSK + if (s->psk_identity_hint) + { + ss->psk_identity_hint = BUF_strdup(s->psk_identity_hint); + if (ss->psk_identity_hint == NULL) + { + SSLerr(SSL_F_SSL_GET_NEW_SESSION, ERR_R_MALLOC_FAILURE); + SSL_SESSION_free(ss); + return 0; + } + } +#endif } else { diff --git a/main/openssl/ssl/tls1.h b/main/openssl/ssl/tls1.h index 6283c6a7..ec8948d5 100644 --- a/main/openssl/ssl/tls1.h +++ b/main/openssl/ssl/tls1.h @@ -531,6 +531,10 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb) #define TLS1_CK_ECDH_RSA_WITH_AES_128_GCM_SHA256 0x0300C031 #define TLS1_CK_ECDH_RSA_WITH_AES_256_GCM_SHA384 0x0300C032 +/* ECDHE PSK ciphersuites from RFC 5489 */ +#define TLS1_CK_ECDHE_PSK_WITH_AES_128_CBC_SHA256 0x0300C037 +#define TLS1_CK_ECDHE_PSK_WITH_AES_256_CBC_SHA384 0x0300C038 + /* XXX * Inconsistency alert: * The OpenSSL names of ciphers with ephemeral DH here include the string @@ -682,6 +686,10 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb) #define TLS1_TXT_ECDH_RSA_WITH_AES_128_GCM_SHA256 "ECDH-RSA-AES128-GCM-SHA256" #define TLS1_TXT_ECDH_RSA_WITH_AES_256_GCM_SHA384 "ECDH-RSA-AES256-GCM-SHA384" +/* ECDHE PSK ciphersuites from RFC 5489 */ +#define TLS1_TXT_ECDHE_PSK_WITH_AES_128_CBC_SHA256 "ECDHE-PSK-WITH-AES-128-CBC-SHA256" +#define TLS1_TXT_ECDHE_PSK_WITH_AES_256_CBC_SHA384 "ECDHE-PSK-WITH-AES-256-CBC-SHA384" + #define TLS_CT_RSA_SIGN 1 #define TLS_CT_DSS_SIGN 2 #define TLS_CT_RSA_FIXED_DH 3 |