Yet another version after some refactorings that landed in master. Please, pretty please, with sugar on top, could anyone review this code so that it can get merged?
It's becoming a difficult exercise to keep track of upstream changes and adapt the patch every single time... Cheers, -- Giuseppe D'Angelo | giuseppe.dang...@kdab.com | Software Engineer KDAB (UK) Ltd., a KDAB Group company | Tel: UK +44-1625-809908 KDAB - The Qt Experts
>From 9f304d4a48494a2f1a46540a9fe775318ed70397 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo <giuseppe.dang...@kdab.com> Date: Sat, 8 Nov 2014 20:44:23 +0100 Subject: [PATCH] Introduce TLS-RSA-PSK support Build on the existing PSK support and introduce RSA-PSK (cf. RFC 4279, 5487). Based on the original patch by Christian J. Dietrich. This work has been sponsored by Governikus GmbH & Co. KG. PR: 2464 --- CHANGES | 3 + doc/apps/ciphers.pod | 12 +++ include/openssl/ssl.h | 2 + include/openssl/tls1.h | 36 ++++++++ ssl/s3_clnt.c | 122 +++++++++++++++++++++---- ssl/s3_lib.c | 208 ++++++++++++++++++++++++++++++++++++++++++- ssl/s3_srvr.c | 235 ++++++++++++++++++++++++++++++++++++++++++++++--- ssl/ssl_ciph.c | 9 +- ssl/ssl_lib.c | 6 ++ ssl/ssl_locl.h | 2 + 10 files changed, 602 insertions(+), 33 deletions(-) diff --git a/CHANGES b/CHANGES index fae1123..243c5d6 100644 --- a/CHANGES +++ b/CHANGES @@ -425,6 +425,9 @@ whose return value is often ignored. [Steve Henson] + *) Support for TLS-RSA-PSK ciphersuites has been added. + [Giuseppe D'Angelo, Christian J. Dietrich] + Changes between 1.0.2a and 1.0.2b [xx XXX xxxx] *) Malformed ECParameters causes infinite loop diff --git a/doc/apps/ciphers.pod b/doc/apps/ciphers.pod index c2d40ac..7fbe3a4 100644 --- a/doc/apps/ciphers.pod +++ b/doc/apps/ciphers.pod @@ -585,10 +585,22 @@ Note: these ciphers can also be used in SSL v3. =head2 Pre shared keying (PSK) ciphersuites + TLS_RSA_PSK_WITH_RC4_128_SHA RSA-PSK-RC4-SHA + TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA RSA-PSK-3DES-EDE-CBC-SHA + TLS_RSA_PSK_WITH_AES_128_CBC_SHA RSA-PSK-AES128-CBC-SHA + TLS_RSA_PSK_WITH_AES_256_CBC_SHA RSA-PSK-AES256-CBC-SHA + TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 RSA-PSK-AES128-CBC-SHA256 + TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 RSA-PSK-AES256-CBC-SHA384 + TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 RSA-PSK-AES128-GCM-SHA256 + TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 RSA-PSK-AES256-GCM-SHA384 TLS_PSK_WITH_RC4_128_SHA PSK-RC4-SHA TLS_PSK_WITH_3DES_EDE_CBC_SHA PSK-3DES-EDE-CBC-SHA TLS_PSK_WITH_AES_128_CBC_SHA PSK-AES128-CBC-SHA TLS_PSK_WITH_AES_256_CBC_SHA PSK-AES256-CBC-SHA + TLS_PSK_WITH_AES_128_CBC_SHA256 PSK-AES128-CBC-SHA256 + TLS_PSK_WITH_AES_256_CBC_SHA384 PSK-AES256-CBC-SHA384 + TLS_PSK_WITH_AES_128_GCM_SHA256 PSK-AES128-GCM-SHA256 + TLS_PSK_WITH_AES_256_GCM_SHA384 PSK-AES256-GCM-SHA384 =head1 NOTES diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h index cd932e5..ded2f48 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h @@ -204,6 +204,7 @@ extern "C" { # define SSL_TXT_kEECDH "kEECDH"/* alias for kECDHE */ # define SSL_TXT_kECDHE "kECDHE" # define SSL_TXT_kPSK "kPSK" +# define SSL_TXT_kRSAPSK "kRSAPSK" # define SSL_TXT_kGOST "kGOST" # define SSL_TXT_kSRP "kSRP" @@ -230,6 +231,7 @@ extern "C" { # define SSL_TXT_AECDH "AECDH" # define SSL_TXT_ECDSA "ECDSA" # define SSL_TXT_PSK "PSK" +# define SSL_TXT_RSAPSK "RSAPSK" # define SSL_TXT_SRP "SRP" # define SSL_TXT_DES "DES" diff --git a/include/openssl/tls1.h b/include/openssl/tls1.h index 40205e1..873c331 100644 --- a/include/openssl/tls1.h +++ b/include/openssl/tls1.h @@ -409,6 +409,24 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb) # define TLS1_CK_PSK_WITH_AES_128_CBC_SHA 0x0300008C # define TLS1_CK_PSK_WITH_AES_256_CBC_SHA 0x0300008D +/* PSK ciphersuites from 5487 */ +# define TLS1_CK_PSK_WITH_AES_128_GCM_SHA256 0x030000A8 +# define TLS1_CK_PSK_WITH_AES_256_GCM_SHA384 0x030000A9 +# define TLS1_CK_PSK_WITH_AES_128_CBC_SHA256 0x030000AE +# define TLS1_CK_PSK_WITH_AES_256_CBC_SHA384 0x030000AF + +/* RSA-PSK ciphersuites from 4279 */ +# define TLS1_CK_RSA_PSK_WITH_RC4_128_SHA 0x03000092 +# define TLS1_CK_RSA_PSK_WITH_3DES_EDE_CBC_SHA 0x03000093 +# define TLS1_CK_RSA_PSK_WITH_AES_128_CBC_SHA 0x03000094 +# define TLS1_CK_RSA_PSK_WITH_AES_256_CBC_SHA 0x03000095 + +/* RSA-PSK ciphersuites from 5487 */ +# define TLS1_CK_RSA_PSK_WITH_AES_128_GCM_SHA256 0x030000AC +# define TLS1_CK_RSA_PSK_WITH_AES_256_GCM_SHA384 0x030000AD +# define TLS1_CK_RSA_PSK_WITH_AES_128_CBC_SHA256 0x030000B6 +# define TLS1_CK_RSA_PSK_WITH_AES_256_CBC_SHA384 0x030000B7 + /* AES ciphersuites from RFC3268 */ # define TLS1_CK_RSA_WITH_AES_128_SHA 0x0300002F @@ -637,6 +655,24 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb) # define TLS1_TXT_PSK_WITH_AES_128_CBC_SHA "PSK-AES128-CBC-SHA" # define TLS1_TXT_PSK_WITH_AES_256_CBC_SHA "PSK-AES256-CBC-SHA" +/* PSK ciphersuites from RFC 5487 */ +# define TLS1_TXT_PSK_WITH_AES_128_GCM_SHA256 "PSK-AES128-GCM-SHA256" +# define TLS1_TXT_PSK_WITH_AES_256_GCM_SHA384 "PSK-AES256-GCM-SHA384" +# define TLS1_TXT_PSK_WITH_AES_128_CBC_SHA256 "PSK-AES128-CBC-SHA256" +# define TLS1_TXT_PSK_WITH_AES_256_CBC_SHA384 "PSK-AES256-CBC-SHA384" + +/* RSA-PSK ciphersuites from RFC 4279 */ +# define TLS1_TXT_RSA_PSK_WITH_RC4_128_SHA "RSA-PSK-RC4-SHA" +# define TLS1_TXT_RSA_PSK_WITH_3DES_EDE_CBC_SHA "RSA-PSK-3DES-EDE-CBC-SHA" +# define TLS1_TXT_RSA_PSK_WITH_AES_128_CBC_SHA "RSA-PSK-AES128-CBC-SHA" +# define TLS1_TXT_RSA_PSK_WITH_AES_256_CBC_SHA "RSA-PSK-AES256-CBC-SHA" + +/* RSA-PSK ciphersuites from RFC 5487 */ +# define TLS1_TXT_RSA_PSK_WITH_AES_128_GCM_SHA256 "RSA-PSK-AES128-GCM-SHA256" +# define TLS1_TXT_RSA_PSK_WITH_AES_256_GCM_SHA384 "RSA-PSK-AES256-GCM-SHA384" +# define TLS1_TXT_RSA_PSK_WITH_AES_128_CBC_SHA256 "RSA-PSK-AES128-CBC-SHA256" +# define TLS1_TXT_RSA_PSK_WITH_AES_256_CBC_SHA384 "RSA-PSK-AES256-CBC-SHA384" + /* SRP ciphersuite from RFC 5054 */ # define TLS1_TXT_SRP_SHA_WITH_3DES_EDE_CBC_SHA "SRP-3DES-EDE-CBC-SHA" # define TLS1_TXT_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA "SRP-RSA-3DES-EDE-CBC-SHA" diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c index 935a621..b693afe 100644 --- a/ssl/s3_clnt.c +++ b/ssl/s3_clnt.c @@ -330,7 +330,7 @@ int ssl3_connect(SSL *s) } /* Check if it is anon DH/ECDH, SRP auth */ - /* or PSK */ + /* or plain PSK */ if (! (s->s3->tmp. new_cipher->algorithm_auth & (SSL_aNULL | SSL_aSRP)) @@ -1449,9 +1449,9 @@ int ssl3_get_key_exchange(SSL *s) } #ifndef OPENSSL_NO_PSK /* - * In plain PSK ciphersuite, ServerKeyExchange can be omitted if no - * identity hint is sent. Set session->sess_cert anyway to avoid - * problems later. + * In PSK ciphersuites, ServerKeyExchange can be omitted if no + * identity hint is sent. Set session->sess_cert for plain PSK + * anyway to avoid problems later. */ if (alg_k & SSL_kPSK) { s->session->sess_cert = ssl_sess_cert_new(); @@ -1489,7 +1489,12 @@ int ssl3_get_key_exchange(SSL *s) al = SSL_AD_DECODE_ERROR; #ifndef OPENSSL_NO_PSK - if (alg_k & SSL_kPSK) { + /* handle PSK identity hint */ + if (alg_k & (SSL_kPSK +#ifndef OPENSSL_NO_RSA + | SSL_kRSAPSK +#endif + )) { char tmp_id_hint[PSK_MAX_IDENTITY_LEN + 1]; param_len = 2; @@ -1643,7 +1648,11 @@ int ssl3_get_key_exchange(SSL *s) } else #endif /* !OPENSSL_NO_SRP */ #ifndef OPENSSL_NO_RSA - if (alg_k & SSL_kRSA) { + if (alg_k & (SSL_kRSA +#ifndef OPENSSL_NO_PSK + | SSL_kRSAPSK +#endif + )) { /* Temporary RSA keys only allowed in export ciphersuites */ if (!SSL_C_IS_EXPORT(s->s3->tmp.new_cipher)) { al = SSL_AD_UNEXPECTED_MESSAGE; @@ -2019,8 +2028,16 @@ 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)) { + /* aNULL, aSRP, kPSK or kRSAPSK do not need public keys */ + if (!(alg_a & (SSL_aNULL | SSL_aSRP)) +#ifndef OPENSSL_NO_PSK + && !(alg_k & (SSL_kPSK +#ifndef OPENSSL_NO_RSA + | SSL_kRSAPSK +#endif + )) +#endif + ) { /* Might be wrong key type, check it */ if (ssl3_check_cert_and_algorithm(s)) /* Otherwise this shouldn't happen */ @@ -2889,7 +2906,11 @@ int ssl3_send_client_key_exchange(SSL *s) } #endif #ifndef OPENSSL_NO_PSK - else if (alg_k & SSL_kPSK) { + else if (alg_k & SSL_kPSK +#ifndef OPENSSL_NO_RSA + || alg_k & SSL_kRSAPSK +#endif + ) { /* * The callback needs PSK_MAX_IDENTITY_LEN + 1 bytes to return a * \0-terminated identity. The last byte is for us for simulating @@ -2927,8 +2948,6 @@ int ssl3_send_client_key_exchange(SSL *s) SSL_R_PSK_IDENTITY_NOT_FOUND); goto psk_err; } - /* Change pmslen to real length */ - pmslen = 2 + psk_len + 2 + psk_len; identity[PSK_MAX_IDENTITY_LEN + 1] = '\0'; identity_len = strlen(identity); if (identity_len > PSK_MAX_IDENTITY_LEN) { @@ -2936,13 +2955,39 @@ int ssl3_send_client_key_exchange(SSL *s) ERR_R_INTERNAL_ERROR); goto psk_err; } + /* create PSK pre_master_secret */ t = pms; - memmove(pms + psk_len + 4, pms, psk_len); - s2n(psk_len, t); - memset(t, 0, psk_len); - t += psk_len; - s2n(psk_len, t); + + if (alg_k & SSL_kPSK) { + /* Change pmslen to real length */ + pmslen = 2 + psk_len + 2 + psk_len; + memmove(pms + psk_len + 4, pms, psk_len); + s2n(psk_len, t); + memset(t, 0, psk_len); + t += psk_len; + s2n(psk_len, t); + } +#ifndef OPENSSL_NO_RSA + else if (alg_k & SSL_kRSAPSK) { + const unsigned int pre_ms_prefix = 48; + + /* Change pmslen to real length */ + pmslen = 2 + 2 + 46 + 2 + psk_len; + + memmove(pms + 52, pms, psk_len); + s2n(pre_ms_prefix, t); + + pms[2] = s->client_version >> 8; + pms[3] = s->client_version & 0xff; + t += 2; + + if (RAND_bytes(pms + 4, 46) <= 0) + goto psk_err; + t += 46; + s2n(psk_len, t); + } +#endif OPENSSL_free(s->session->psk_identity_hint); s->session->psk_identity_hint = @@ -2964,8 +3009,41 @@ int ssl3_send_client_key_exchange(SSL *s) s2n(identity_len, p); memcpy(p, identity, identity_len); + p += identity_len; n = 2 + identity_len; + +#ifndef OPENSSL_NO_RSA + if (alg_k & SSL_kRSAPSK) { + RSA *rsa; + int enc_n; + + if (s->session->sess_cert->peer_rsa_tmp != NULL) { + rsa = s->session->sess_cert->peer_rsa_tmp; + } else { + pkey = X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509); + if ((pkey == NULL) || (pkey->type != EVP_PKEY_RSA) || (pkey->pkey.rsa == NULL)) { + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); + goto psk_err; + } + rsa = pkey->pkey.rsa; + EVP_PKEY_free(pkey); + } + + enc_n = RSA_public_encrypt(48, pms + 2, p + 2, rsa, RSA_PKCS1_PADDING); + if (enc_n <= 0) { + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, SSL_R_BAD_RSA_ENCRYPT); + goto psk_err; + } + + n += enc_n; + + s2n(enc_n, p); + n += 2; + } +#endif + psk_err = 0; + psk_err: OPENSSL_cleanse(identity, sizeof(identity)); if (psk_err != 0) { @@ -3403,7 +3481,11 @@ int ssl3_check_cert_and_algorithm(SSL *s) } #endif #ifndef OPENSSL_NO_RSA - if (alg_k & SSL_kRSA) { + if (alg_k & (SSL_kRSA +#ifndef OPENSSL_NO_PSK + | SSL_kRSAPSK +#endif + )) { if (!SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && !has_bits(i, EVP_PK_RSA | EVP_PKT_ENC)) { SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, @@ -3450,7 +3532,11 @@ int ssl3_check_cert_and_algorithm(SSL *s) if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && pkey_bits > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) { #ifndef OPENSSL_NO_RSA - if (alg_k & SSL_kRSA) { + if (alg_k & (SSL_kRSA +#ifndef OPENSSL_NO_PSK + | SSL_kRSAPSK +#endif + )) { if (rsa == NULL) { SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, SSL_R_MISSING_EXPORT_TMP_RSA_KEY); diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c index 0307801..eae444b 100644 --- a/ssl/s3_lib.c +++ b/ssl/s3_lib.c @@ -1316,6 +1316,74 @@ OPENSSL_GLOBAL const SSL_CIPHER ssl3_ciphers[] = { 256, 256, }, + + +#ifndef OPENSSL_NO_RSA + /* RSA-PSK ciphersuites from RFC4279 */ + /* Cipher 92 */ + { + 1, + TLS1_TXT_RSA_PSK_WITH_RC4_128_SHA, + TLS1_CK_RSA_PSK_WITH_RC4_128_SHA, + SSL_kRSAPSK, + SSL_aRSA, + SSL_RC4, + SSL_SHA1, + SSL_TLSV1, + SSL_NOT_EXP|SSL_MEDIUM, + SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, + 128, + 128, + }, + + /* Cipher 93 */ + { + 1, + TLS1_TXT_RSA_PSK_WITH_3DES_EDE_CBC_SHA, + TLS1_CK_RSA_PSK_WITH_3DES_EDE_CBC_SHA, + SSL_kRSAPSK, + SSL_aRSA, + SSL_3DES, + SSL_SHA1, + SSL_TLSV1, + SSL_NOT_EXP|SSL_HIGH, + SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, + 112, + 168, + }, + + /* Cipher 94 */ + { + 1, + TLS1_TXT_RSA_PSK_WITH_AES_128_CBC_SHA, + TLS1_CK_RSA_PSK_WITH_AES_128_CBC_SHA, + SSL_kRSAPSK, + SSL_aRSA, + SSL_AES128, + SSL_SHA1, + SSL_TLSV1, + SSL_NOT_EXP|SSL_HIGH, + SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, + 128, + 128, + }, + + /* Cipher 95 */ + { + 1, + TLS1_TXT_RSA_PSK_WITH_AES_256_CBC_SHA, + TLS1_CK_RSA_PSK_WITH_AES_256_CBC_SHA, + SSL_kRSAPSK, + SSL_aRSA, + SSL_AES256, + SSL_SHA1, + SSL_TLSV1, + SSL_NOT_EXP|SSL_HIGH, + SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, + 256, + 256, + }, +#endif /* OPENSSL_NO_RSA */ #endif /* OPENSSL_NO_PSK */ #ifndef OPENSSL_NO_SEED @@ -1613,6 +1681,144 @@ OPENSSL_GLOBAL const SSL_CIPHER ssl3_ciphers[] = { 256, }, +#ifndef OPENSSL_NO_PSK + /* PSK ciphersuites from RFC5487 */ + +#if 0 /* The GCM variants will crash into s3_pkt.c, need to debug that */ + /* Cipher A8 */ + { + 1, + TLS1_TXT_PSK_WITH_AES_128_GCM_SHA256, + TLS1_CK_PSK_WITH_AES_128_GCM_SHA256, + SSL_kPSK, + SSL_aPSK, + SSL_AES128GCM, + SSL_SHA256, + SSL_TLSV1_2, + SSL_NOT_EXP|SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256, + 128, + 128, + }, + + /* Cipher A9 */ + { + 1, + TLS1_TXT_PSK_WITH_AES_256_GCM_SHA384, + TLS1_CK_PSK_WITH_AES_256_GCM_SHA384, + SSL_kPSK, + SSL_aPSK, + SSL_AES256GCM, + SSL_SHA384, + SSL_TLSV1_2, + SSL_NOT_EXP|SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA384|TLS1_PRF_SHA384, + 256, + 256, + }, + + #ifndef OPENSSL_NO_RSA + /* Cipher AC */ + { + 1, + TLS1_TXT_RSA_PSK_WITH_AES_128_GCM_SHA256, + TLS1_CK_RSA_PSK_WITH_AES_128_GCM_SHA256, + SSL_kRSAPSK, + SSL_aRSA, + SSL_AES128GCM, + SSL_SHA256, + SSL_TLSV1_2, + SSL_NOT_EXP|SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256, + 128, + 128, + }, + + /* Cipher AD */ + { + 1, + TLS1_TXT_RSA_PSK_WITH_AES_256_GCM_SHA384, + TLS1_CK_RSA_PSK_WITH_AES_256_GCM_SHA384, + SSL_kRSAPSK, + SSL_aRSA, + SSL_AES256GCM, + SSL_SHA384, + SSL_TLSV1_2, + SSL_NOT_EXP|SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA384|TLS1_PRF_SHA384, + 256, + 256, + }, +#endif /* OPENSSL_NO_RSA */ +#endif /* 0 */ + + /* Cipher AE */ + { + 1, + TLS1_TXT_PSK_WITH_AES_128_CBC_SHA256, + TLS1_CK_PSK_WITH_AES_128_CBC_SHA256, + SSL_kPSK, + SSL_aPSK, + SSL_AES128, + SSL_SHA256, + SSL_TLSV1, + SSL_NOT_EXP|SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256, + 128, + 128, + }, + + /* Cipher AF */ + { + 1, + TLS1_TXT_PSK_WITH_AES_256_CBC_SHA384, + TLS1_CK_PSK_WITH_AES_256_CBC_SHA384, + SSL_kPSK, + SSL_aPSK, + SSL_AES256, + SSL_SHA384, + SSL_TLSV1, + SSL_NOT_EXP|SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA384|TLS1_PRF_SHA384, + 256, + 256, + }, + + #ifndef OPENSSL_NO_RSA + /* Cipher B6 */ + { + 1, + TLS1_TXT_RSA_PSK_WITH_AES_128_CBC_SHA256, + TLS1_CK_RSA_PSK_WITH_AES_128_CBC_SHA256, + SSL_kRSAPSK, + SSL_aRSA, + SSL_AES128, + SSL_SHA256, + SSL_TLSV1, + SSL_NOT_EXP|SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256, + 128, + 128, + }, + + /* Cipher B7 */ + { + 1, + TLS1_TXT_RSA_PSK_WITH_AES_256_CBC_SHA384, + TLS1_CK_RSA_PSK_WITH_AES_256_CBC_SHA384, + SSL_kRSAPSK, + SSL_aRSA, + SSL_AES256, + SSL_SHA384, + SSL_TLSV1, + SSL_NOT_EXP|SSL_HIGH, + SSL_HANDSHAKE_MAC_SHA384|TLS1_PRF_SHA384, + 256, + 256, + }, +#endif /* OPENSSL_NO_RSA */ +#endif /* OPENSSL_NO_PSK */ + #ifndef OPENSSL_NO_CAMELLIA /* TLS 1.2 Camellia SHA-256 ciphersuites from RFC5932 */ @@ -3889,7 +4095,7 @@ SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt, #ifndef OPENSSL_NO_PSK /* with PSK there must be server callback set */ - if ((alg_k & SSL_kPSK) && s->psk_server_callback == NULL) + if ((alg_k & (SSL_kPSK | SSL_kRSAPSK)) && s->psk_server_callback == NULL) continue; #endif /* OPENSSL_NO_PSK */ diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c index 90a67d1..8970631 100644 --- a/ssl/s3_srvr.c +++ b/ssl/s3_srvr.c @@ -434,19 +434,23 @@ int ssl3_accept(SSL *s) /* * only send if a DH key exchange, fortezza or RSA but we have a - * sign only certificate PSK: may send PSK identity hints For - * ECC ciphersuites, we send a serverKeyExchange message only if + * sign only certificate + * + * PSK|RSAPSK: may send PSK identity hints. + * Send ServerKeyExchange if PSK identity hint is provided. + * + * For ECC ciphersuites, we send a serverKeyExchange message only if * the cipher suite is either ECDH-anon or ECDHE. In other cases, * the server certificate contains the server's public key for * key exchange. */ if (0 - /* - * 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 +#ifndef OPENSSL_NO_RSA + | SSL_kRSAPSK +#endif + )) && s->ctx->psk_identity_hint) #endif #ifndef OPENSSL_NO_SRP /* SRP: send ServerKeyExchange */ @@ -498,11 +502,14 @@ int ssl3_accept(SSL *s) !(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) || /* don't request certificate for SRP auth */ (s->s3->tmp.new_cipher->algorithm_auth & SSL_aSRP) +#ifndef OPENSSL_NO_PSK /* - * With normal PSK Certificates and Certificate Requests + * With normal PSK, Certificates and Certificate Requests * are omitted */ - || (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) { + || (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK) +#endif + ) { /* no cert request */ skip = 1; s->s3->tmp.cert_request = 0; @@ -1953,7 +1960,11 @@ int ssl3_send_server_key_exchange(SSL *s) } else #endif /* !OPENSSL_NO_EC */ #ifndef OPENSSL_NO_PSK - if (type & SSL_kPSK) { + if (type & (SSL_kPSK +#ifndef OPENSSL_NO_RSA + | SSL_kRSAPSK +#endif + )) { /* * reserve size for record length and PSK identity hint */ @@ -1992,7 +2003,14 @@ int ssl3_send_server_key_exchange(SSL *s) } if (!(s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL | SSL_aSRP)) - && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) { +#ifndef OPENSSL_NO_PSK + && !(s->s3->tmp.new_cipher->algorithm_mkey & (SSL_kPSK +#ifndef OPENSSL_NO_RSA + | SSL_kRSAPSK +#endif + )) +#endif + ) { if ((pkey = ssl_get_sign_pkey(s, s->s3->tmp.new_cipher, &md)) == NULL) { al = SSL_AD_DECODE_ERROR; @@ -2046,7 +2064,11 @@ int ssl3_send_server_key_exchange(SSL *s) #endif #ifndef OPENSSL_NO_PSK - if (type & SSL_kPSK) { + if (type & (SSL_kPSK +#ifndef OPENSSL_NO_RSA + | SSL_kRSAPSK +#endif + )) { /* copy PSK identity hint */ s2n(strlen(s->ctx->psk_identity_hint), p); strncpy((char *)p, s->ctx->psk_identity_hint, @@ -2062,7 +2084,11 @@ int ssl3_send_server_key_exchange(SSL *s) * points to the space at the end. */ #ifndef OPENSSL_NO_RSA - if (pkey->type == EVP_PKEY_RSA && !SSL_USE_SIGALGS(s)) { + if (pkey->type == EVP_PKEY_RSA && !SSL_USE_SIGALGS(s) +#ifndef OPENSSL_NO_PSK + && !(type & SSL_kRSAPSK) +#endif + ) { q = md_buf; j = 0; for (num = 2; num > 0; num--) { @@ -2732,6 +2758,189 @@ int ssl3_get_client_key_exchange(SSL *s) goto f_err; } else #endif +#ifndef OPENSSL_NO_RSA +#ifndef OPENSSL_NO_PSK + if (alg_k & SSL_kRSAPSK) { + unsigned char rand_premaster_secret[SSL_MAX_MASTER_KEY_LENGTH]; + int decrypt_len; + unsigned char decrypt_good, version_good; + unsigned char *orig_p = p; + + unsigned int psk_len; + + const unsigned int pre_master_secret_prefix = 48; + unsigned char psk_or_pre_ms[PSK_MAX_PSK_LEN * 2 + 4]; + unsigned int pre_ms_len; + unsigned char *t = psk_or_pre_ms; + + char identity[PSK_MAX_IDENTITY_LEN + 1]; + int identity_len; + + int epms_len; + int psk_err = 1; + + /* No server callback? Bail out */ + if (s->psk_server_callback == NULL) { + al = SSL_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_PSK_NO_SERVER_CB); + goto f_err; + } + + /* FIX THIS UP EAY EAY EAY EAY */ + if (s->s3->tmp.use_rsa_tmp) { + if ((s->cert != NULL) && (s->cert->rsa_tmp != NULL)) + rsa = s->cert->rsa_tmp; + /* + * Don't do a callback because rsa_tmp should be sent already + */ + if (rsa == NULL) { + al = SSL_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + SSL_R_MISSING_TMP_RSA_PKEY); + goto f_err; + + } + } else { + pkey = s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey; + if ((pkey == NULL) || + (pkey->type != EVP_PKEY_RSA) || (pkey->pkey.rsa == NULL)) { + al = SSL_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + SSL_R_MISSING_RSA_CERTIFICATE); + goto f_err; + } + rsa = pkey->pkey.rsa; + } + + /* Extract the PSK identity */ + if (n < (2 + 2)) { /* 2 bytes for the identity len, 2 bytes for the epms len */ + al = SSL_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + SSL_R_LENGTH_MISMATCH); + goto f_err; + } + + n2s(p, identity_len); + + if (identity_len > PSK_MAX_IDENTITY_LEN) { + al = SSL_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + SSL_R_DATA_LENGTH_TOO_LONG); + goto f_err; + } + + if (n < (2 + identity_len + 2)) { /* as above, plus the identity len */ + al = SSL_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + SSL_R_LENGTH_MISMATCH); + goto f_err; + } + + memset(identity, 0, sizeof(identity)); + memcpy(identity, p, identity_len); + p += identity_len; + + /* fill the pre master secret with random bytes */ + if (RAND_bytes(psk_or_pre_ms, sizeof(psk_or_pre_ms)) <= 0) + goto err; + + /* read the psk (into the beginning of the psk_or_pre_ms buffer */ + psk_len = s->psk_server_callback(s, identity, psk_or_pre_ms, sizeof(psk_or_pre_ms)); + if (psk_len > PSK_MAX_PSK_LEN) { + al = SSL_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + ERR_R_INTERNAL_ERROR); + goto rsapsk_err; + } else if (psk_len == 0) { + al = SSL_AD_UNKNOWN_PSK_IDENTITY; + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + SSL_R_PSK_IDENTITY_NOT_FOUND); + goto rsapsk_err; + } + + /* move on onto decoding the 48 encrypted bytes */ + + /* how many bytes to decode? */ + n2s(p, epms_len); + + if (n != (2 + identity_len + 2 + epms_len)) { /* as above */ + al = SSL_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + SSL_R_LENGTH_MISMATCH); + goto rsapsk_err; + } + + /* decode in place into p */ + decrypt_len = RSA_private_decrypt(epms_len, p, p, rsa, RSA_PKCS1_PADDING); + decrypt_good = constant_time_eq_int_8(decrypt_len, 48); + + /* check the version sent by the client */ + version_good = constant_time_eq_8(p[0], (unsigned)(s->client_version >> 8)); + version_good &= constant_time_eq_8(p[1], (unsigned)(s->client_version & 0xff)); + + decrypt_good &= version_good; + + for (i = 0; i < (int) sizeof(rand_premaster_secret); i++) + p[i] = constant_time_select_8(decrypt_good, p[i], rand_premaster_secret[i]); + + /* + * build the pre master secret. it should look like this: + * 48 (2b) + version (2b) + random (46b) + psk_len (2b) + psk + */ + pre_ms_len = 2 + 2 + 46 + 2 + psk_len; + + /* the PSK is at the beginning of psk_or_pre_ms, move at the end */ + memmove(psk_or_pre_ms + 52, psk_or_pre_ms, psk_len); + + /* fill the "48" in */ + s2n(pre_master_secret_prefix, t); + + /* fill the 2 bytes version + the 46 random bytes (decrypted earlier with RSA) */ + memcpy(t, p, 48); + t += 48; + + /* fill the psk_len */ + s2n(psk_len, t); + + /* psk_or_pre_ms now contains the pre master secret */ + + /* set the identity in the session */ + if (s->session->psk_identity != NULL) + OPENSSL_free(s->session->psk_identity); + + s->session->psk_identity = BUF_strdup(identity); + OPENSSL_cleanse(identity, sizeof(identity)); + + if (s->session->psk_identity == NULL) { + al=SSL_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE); + goto rsapsk_err; + } + + /* set the identity hint in the session */ + 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) { + al = SSL_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE); + goto rsapsk_err; + } + + /* set the premaster key */ + 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; + rsapsk_err: + OPENSSL_cleanse(orig_p, n); /* clear the whole payload area */ + if (psk_err != 0) + goto f_err; + } else +#endif +#endif #ifndef OPENSSL_NO_SRP if (alg_k & SSL_kSRP) { int param_len; diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c index 7f932b0..459c6c2 100644 --- a/ssl/ssl_ciph.c +++ b/ssl/ssl_ciph.c @@ -314,6 +314,7 @@ static const SSL_CIPHER cipher_aliases[] = { 0, 0, 0}, {0, SSL_TXT_kPSK, 0, SSL_kPSK, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, SSL_TXT_kRSAPSK, 0, SSL_kRSAPSK, 0, 0, 0, 0, 0, 0, 0, 0}, {0, SSL_TXT_kSRP, 0, SSL_kSRP, 0, 0, 0, 0, 0, 0, 0, 0}, {0, SSL_TXT_kGOST, 0, SSL_kGOST, 0, 0, 0, 0, 0, 0, 0, 0}, @@ -343,6 +344,7 @@ static const SSL_CIPHER cipher_aliases[] = { {0, SSL_TXT_ADH, 0, SSL_kDHE, SSL_aNULL, 0, 0, 0, 0, 0, 0, 0}, {0, SSL_TXT_AECDH, 0, SSL_kECDHE, SSL_aNULL, 0, 0, 0, 0, 0, 0, 0}, {0, SSL_TXT_PSK, 0, SSL_kPSK, SSL_aPSK, 0, 0, 0, 0, 0, 0, 0}, + {0, SSL_TXT_RSAPSK, 0, SSL_kRSAPSK, SSL_aRSA, 0, 0, 0, 0, 0, 0, 0}, {0, SSL_TXT_SRP, 0, SSL_kSRP, 0, 0, 0, 0, 0, 0, 0, 0}, /* symmetric encryption aliases */ @@ -507,7 +509,7 @@ void ssl_load_ciphers(void) disabled_auth_mask |= SSL_aECDSA | SSL_aECDH; #endif #ifdef OPENSSL_NO_PSK - disabled_mkey_mask |= SSL_kPSK; + disabled_mkey_mask |= SSL_kPSK | SSL_kRSAPSK; disabled_auth_mask |= SSL_aPSK; #endif #ifdef OPENSSL_NO_SRP @@ -1466,6 +1468,8 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method, STACK */ ssl_cipher_apply_rule(0, SSL_kRSA, 0, 0, 0, 0, 0, CIPHER_ORD, -1, &head, &tail); + ssl_cipher_apply_rule(0, SSL_kRSAPSK, 0, 0, 0, 0, 0, CIPHER_ORD, -1, &head, + &tail); ssl_cipher_apply_rule(0, SSL_kPSK, 0, 0, 0, 0, 0, CIPHER_ORD, -1, &head, &tail); @@ -1626,6 +1630,9 @@ char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf, int len) case SSL_kPSK: kx = "PSK"; break; + case SSL_kRSAPSK: + kx = "RSAPSK"; + break; case SSL_kSRP: kx = "SRP"; break; diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index 5c814fd..413df1d 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -2110,8 +2110,14 @@ void ssl_set_masks(SSL *s, const SSL_CIPHER *cipher) #ifndef OPENSSL_NO_PSK mask_k |= SSL_kPSK; +#ifndef OPENSSL_NO_RSA + mask_k |= SSL_kRSAPSK; +#endif mask_a |= SSL_aPSK; emask_k |= SSL_kPSK; +#ifndef OPENSSL_NO_RSA + emask_k |= SSL_kRSAPSK; +#endif emask_a |= SSL_aPSK; #endif diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h index 3252631..6519ce4 100644 --- a/ssl/ssl_locl.h +++ b/ssl/ssl_locl.h @@ -314,6 +314,8 @@ # define SSL_kGOST 0x00000200L /* SRP */ # define SSL_kSRP 0x00000400L +/* RSA PSK */ +# define SSL_kRSAPSK 0x00000800L /* Bits for algorithm_auth (server authentication) */ /* RSA auth */ -- 1.9.1
smime.p7s
Description: S/MIME cryptographic signature
_______________________________________________ openssl-dev mailing list To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-dev