From 8a0a12e5bf78e6f2e501d3af86c675498e6c7552 Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Sun, 28 Jun 2015 16:58:00 +0100 Subject: [PATCH] PSK premaster secret derivation. Move PSK premaster secret algorithm to ssl_generate_master secret so existing key exchange code can be used and modified slightly to add the PSK wrapping structure. Reviewed-by: Matt Caswell --- ssl/s3_lib.c | 53 +++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 46 insertions(+), 7 deletions(-) diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c index 527ec1f946..e4c0f58c33 100644 --- a/ssl/s3_lib.c +++ b/ssl/s3_lib.c @@ -4259,13 +4259,52 @@ int ssl_fill_hello_random(SSL *s, int server, unsigned char *result, int len) int ssl_generate_master_secret(SSL *s, unsigned char *pms, size_t pmslen, int free_pms) { - s->session->master_key_length = - s->method->ssl3_enc->generate_master_secret(s, s->session->master_key, - pms, pmslen); - if (free_pms) - OPENSSL_clear_free(pms, pmslen); - else - OPENSSL_cleanse(pms, pmslen); +#ifndef OPENSSL_NO_PSK + unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey; + if (alg_k & SSL_PSK) { + unsigned char *pskpms, *t; + size_t psklen = s->s3->tmp.psklen; + size_t pskpmslen; + + /* create PSK premaster_secret */ + + /* For plain PSK "other_secret" is psklen zeroes */ + if (alg_k & SSL_kPSK) + pmslen = psklen; + + pskpmslen = 4 + pmslen + psklen; + pskpms = OPENSSL_malloc(pskpmslen); + if (pskpms == NULL) + return 0; + t = pskpms; + s2n(pmslen, t); + if (alg_k & SSL_kPSK) + memset(t, 0, pmslen); + else + memcpy(t, pms, pmslen); + t += pmslen; + s2n(psklen, t); + memcpy(t, s->s3->tmp.psk, psklen); + + OPENSSL_clear_free(s->s3->tmp.psk, psklen); + s->s3->tmp.psk = NULL; + s->session->master_key_length = + s->method->ssl3_enc->generate_master_secret(s, + s->session->master_key, + pskpms, pskpmslen); + OPENSSL_clear_free(pskpms, pskpmslen); + } else +#endif + s->session->master_key_length = + s->method->ssl3_enc->generate_master_secret(s, + s->session->master_key, + pms, pmslen); + if (pms) { + if (free_pms) + OPENSSL_clear_free(pms, pmslen); + else + OPENSSL_cleanse(pms, pmslen); + } if (s->server == 0) s->s3->tmp.pms = NULL; return s->session->master_key_length >= 0;