| From c8b1f7ec56704c1116795aec9ca61db654b433bf Mon Sep 17 00:00:00 2001 |
| From: Alex Klyubin <klyubin@google.com> |
| Date: Mon, 19 May 2014 11:27:33 -0700 |
| Subject: psk_client_callback, 128-byte id bug. |
| |
| Fix a bug in handling of 128 byte long PSK identity in |
| psk_client_callback. |
| |
| OpenSSL supports PSK identities of up to (and including) 128 bytes in |
| length. PSK identity is obtained via the psk_client_callback, |
| implementors of which are expected to provide a NULL-terminated |
| identity. However, the callback is invoked with only 128 bytes of |
| storage thus making it impossible to return a 128 byte long identity and |
| the required additional NULL byte. |
| |
| This CL fixes the issue by passing in a 129 byte long buffer into the |
| psk_client_callback. As a safety precaution, this CL also zeroes out the |
| buffer before passing it into the callback, uses strnlen for obtaining |
| the length of the identity returned by the callback, and aborts the |
| handshake if the identity (without the NULL terminator) is longer than |
| 128 bytes. |
| --- |
| ssl/s3_clnt.c | 20 ++++++++++++++------ |
| 1 file changed, 14 insertions(+), 6 deletions(-) |
| |
| diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c |
| index 03b96e8..0e22afc 100644 |
| --- a/ssl/s3_clnt.c |
| +++ b/ssl/s3_clnt.c |
| @@ -2328,7 +2328,8 @@ int ssl3_send_client_key_exchange(SSL *s) |
| #ifndef OPENSSL_NO_PSK |
| if (alg_a & SSL_aPSK) |
| { |
| - char identity[PSK_MAX_IDENTITY_LEN]; |
| + 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; |
| @@ -2342,8 +2343,9 @@ int ssl3_send_client_key_exchange(SSL *s) |
| goto err; |
| } |
| |
| + memset(identity, 0, sizeof(identity)); |
| psk_len = s->psk_client_callback(s, s->session->psk_identity_hint, |
| - identity, PSK_MAX_IDENTITY_LEN, psk, sizeof(psk)); |
| + identity, sizeof(identity), psk, sizeof(psk)); |
| if (psk_len > PSK_MAX_PSK_LEN) |
| { |
| SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, |
| @@ -2356,6 +2358,13 @@ int ssl3_send_client_key_exchange(SSL *s) |
| 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)) |
| { |
| @@ -2372,10 +2381,9 @@ int ssl3_send_client_key_exchange(SSL *s) |
| s->method->ssl3_enc->generate_master_secret(s, |
| s->session->master_key, |
| pre_ms, pre_ms_len); |
| - n = strlen(identity); |
| - s2n(n, p); |
| - memcpy(p, identity, n); |
| - n += 2; |
| + s2n(identity_len, p); |
| + memcpy(p, identity, identity_len); |
| + n = 2 + identity_len; |
| } |
| |
| if (s->session->psk_identity != NULL) |
| -- |
| 2.0.0.526.g5318336 |
| |