Hi, new version of the patch, adding also the PSK variants defined in RFC 5487 (basically, SHA256 and SHA384 support for both plain PSK and RSA-PSK).
I also sketched up the support for the AES-GCM variants, but using them results in a crash inside s3_pkt.c. I'm still not sure what I'm doing wrong, but I've disabled the corresponding code... Lastly: does it make sense for this patch to target master? Should it be targeting 1.0.2 instead? Thanks, -- Giuseppe D'Angelo | giuseppe.dang...@kdab.com | Software Engineer KDAB (UK) Ltd., a KDAB Group company Tel. UK +44-1738-450410, Sweden (HQ) +46-563-540090 KDAB - Qt Experts - Platform-independent software solutions
>From b3f71ae0386f8bbaba23e6263d752da6c7ef030a 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 +++ ssl/s3_clnt.c | 130 +++++++++++++++++++++++----- ssl/s3_lib.c | 207 +++++++++++++++++++++++++++++++++++++++++++- ssl/s3_srvr.c | 232 +++++++++++++++++++++++++++++++++++++++++++++++--- ssl/ssl.h | 4 +- ssl/ssl_ciph.c | 16 ++-- ssl/ssl_lib.c | 6 ++ ssl/ssl_locl.h | 1 + ssl/tls1.h | 36 ++++++++ 10 files changed, 610 insertions(+), 37 deletions(-) diff --git a/CHANGES b/CHANGES index d90febc..8b48914 100644 --- a/CHANGES +++ b/CHANGES @@ -303,6 +303,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.1j and 1.0.2 [xx XXX xxxx] *) Tighten client-side session ticket handling during renegotiation: diff --git a/doc/apps/ciphers.pod b/doc/apps/ciphers.pod index c41a297..b1f4517 100644 --- a/doc/apps/ciphers.pod +++ b/doc/apps/ciphers.pod @@ -600,10 +600,22 @@ Note: these ciphers can also be used in SSL v3. =head2 Pre shared keying (PSK) cipheruites + 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 =head2 Deprecated SSL v2.0 cipher suites. diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c index 68c00c5..bbcebcb 100644 --- a/ssl/s3_clnt.c +++ b/ssl/s3_clnt.c @@ -343,7 +343,7 @@ int ssl3_connect(SSL *s) } #endif /* 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)) && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) { @@ -1417,9 +1417,9 @@ int ssl3_get_key_exchange(SSL *s) if (s->s3->tmp.message_type != SSL3_MT_SERVER_KEY_EXCHANGE) { #ifndef OPENSSL_NO_PSK - /* In plain PSK ciphersuite, ServerKeyExchange can be + /* In PSK ciphersuites, ServerKeyExchange can be omitted if no identity hint is sent. Set - session->sess_cert anyway to avoid problems + session->sess_cert for plain PSK anyway to avoid problems later.*/ if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK) { @@ -1473,7 +1473,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]; @@ -1650,7 +1655,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 + )) { if ((rsa=RSA_new()) == NULL) { @@ -2061,8 +2070,16 @@ fprintf(stderr, "USING TLSv1.2 HASH %s\n", EVP_MD_name(md)); } 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)) @@ -3132,15 +3149,19 @@ 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 strnlen. */ char identity[PSK_MAX_IDENTITY_LEN + 2]; size_t identity_len; - unsigned char *t = NULL; unsigned char psk_or_pre_ms[PSK_MAX_PSK_LEN*2+4]; + unsigned char *t = psk_or_pre_ms; unsigned int pre_ms_len = 0, psk_len = 0; int psk_err = 1; @@ -3176,14 +3197,36 @@ int ssl3_send_client_key_exchange(SSL *s) ERR_R_INTERNAL_ERROR); 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 (alg_k & SSL_kPSK) + { + /* create PSK pre_master_secret */ + pre_ms_len = 2+psk_len+2+psk_len; + 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); + } +#ifndef OPENSSL_NO_RSA + else if (alg_k & SSL_kRSAPSK) + { + const unsigned int pre_ms_prefix = 48; + + pre_ms_len = 2 + 2 + 46 + 2 + psk_len; + memmove(psk_or_pre_ms + 52, psk_or_pre_ms, psk_len); + s2n(pre_ms_prefix, t); + + psk_or_pre_ms[2] = s->client_version >> 8; + psk_or_pre_ms[3] = s->client_version & 0xff; + t += 2; + + if (RAND_bytes(psk_or_pre_ms + 4, 46) <= 0) + goto psk_err; + t += 46; + s2n(psk_len, t); + } +#endif if (s->session->psk_identity_hint != NULL) OPENSSL_free(s->session->psk_identity_hint); @@ -3210,10 +3253,51 @@ int ssl3_send_client_key_exchange(SSL *s) s->method->ssl3_enc->generate_master_secret(s, s->session->master_key, psk_or_pre_ms, pre_ms_len); + 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, psk_or_pre_ms + 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)); OPENSSL_cleanse(psk_or_pre_ms, sizeof(psk_or_pre_ms)); @@ -3625,7 +3709,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 + )) && !(has_bits(i,EVP_PK_RSA|EVP_PKT_ENC) || (rsa != NULL))) { SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_RSA_ENCRYPTING_CERT); @@ -3658,7 +3746,11 @@ int ssl3_check_cert_and_algorithm(SSL *s) if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && !has_bits(i,EVP_PKT_EXP)) { #ifndef OPENSSL_NO_RSA - if (alg_k & SSL_kRSA) + if (alg_k & (SSL_kRSA +#ifndef OPENSSL_NO_PSK + |SSL_kRSAPSK +#endif + )) { if (rsa == NULL || RSA_size(rsa)*8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c index d670ff0..fb0f683 100644 --- a/ssl/s3_lib.c +++ b/ssl/s3_lib.c @@ -1715,6 +1715,73 @@ 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 @@ -2028,6 +2095,144 @@ OPENSSL_GLOBAL const SSL_CIPHER ssl3_ciphers[]={ }, #endif +#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 */ @@ -4522,7 +4727,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_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 bef055a..55d426a 100644 --- a/ssl/s3_srvr.c +++ b/ssl/s3_srvr.c @@ -467,7 +467,8 @@ 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 + * 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 @@ -476,10 +477,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 */ #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 */ @@ -525,9 +528,11 @@ int ssl3_accept(SSL *s) (s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5) || /* don't request certificate for SRP auth */ (s->s3->tmp.new_cipher->algorithm_auth & SSL_aSRP) - /* With normal PSK Certificates and +#ifndef OPENSSL_NO_PSK + /* With normal PSK, Certificates and * Certificate Requests are omitted */ || (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) +#endif { /* no cert request */ skip=1; @@ -1870,7 +1875,11 @@ int ssl3_send_server_key_exchange(SSL *s) else #endif /* !OPENSSL_NO_ECDH */ #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*/ n+=2+strlen(s->ctx->psk_identity_hint); @@ -1894,7 +1903,7 @@ int ssl3_send_server_key_exchange(SSL *s) r[3]=s->srp_ctx.B; } else -#endif +#endif /*! OPENSSL_NO_SRP */ { al=SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE); @@ -1912,7 +1921,13 @@ 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) @@ -1977,7 +1992,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); @@ -1992,7 +2011,11 @@ int ssl3_send_server_key_exchange(SSL *s) /* n is the length of the params, they start at &(d[4]) * and p 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; @@ -2878,8 +2901,195 @@ int ssl3_get_client_key_exchange(SSL *s) if (psk_err != 0) goto f_err; } - else + 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) + { + 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 */ + { + 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) + { + 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 */ + { + 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_pseudo_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) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + ERR_R_INTERNAL_ERROR); + goto rsapsk_err; + } + else if (psk_len == 0) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + SSL_R_PSK_IDENTITY_NOT_FOUND); + al=SSL_AD_UNKNOWN_PSK_IDENTITY; + 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 */ + { + 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) + { + 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) + { + 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 /* !OPENSSL_NO_PSK */ +#endif /* !OPENSSL_NO_RSA */ #ifndef OPENSSL_NO_SRP if (alg_k & SSL_kSRP) { diff --git a/ssl/ssl.h b/ssl/ssl.h index 343247c..0f47f71 100644 --- a/ssl/ssl.h +++ b/ssl/ssl.h @@ -252,7 +252,8 @@ extern "C" { #define SSL_TXT_kECDH "kECDH" #define SSL_TXT_kEECDH "kEECDH" /* alias for kECDHE */ #define SSL_TXT_kECDHE "kECDHE" -#define SSL_TXT_kPSK "kPSK" +#define SSL_TXT_kPSK "kPSK" +#define SSL_TXT_kRSAPSK "kRSAPSK" #define SSL_TXT_kGOST "kGOST" #define SSL_TXT_kSRP "kSRP" @@ -281,6 +282,7 @@ extern "C" { #define SSL_TXT_ECDSA "ECDSA" #define SSL_TXT_KRB5 "KRB5" #define SSL_TXT_PSK "PSK" +#define SSL_TXT_RSAPSK "RSAPSK" #define SSL_TXT_SRP "SRP" #define SSL_TXT_DES "DES" diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c index 3c005f7..72f67f1 100644 --- a/ssl/ssl_ciph.c +++ b/ssl/ssl_ciph.c @@ -254,7 +254,8 @@ static const SSL_CIPHER cipher_aliases[]={ {0,SSL_TXT_kECDHE,0, SSL_kECDHE,0,0,0,0,0,0,0,0}, {0,SSL_TXT_ECDH,0, SSL_kECDHr|SSL_kECDHe|SSL_kECDHE,0,0,0,0,0,0,0,0}, - {0,SSL_TXT_kPSK,0, SSL_kPSK, 0,0,0,0,0,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}, @@ -268,7 +269,7 @@ static const SSL_CIPHER cipher_aliases[]={ {0,SSL_TXT_aECDH,0, 0,SSL_aECDH, 0,0,0,0,0,0,0}, {0,SSL_TXT_aECDSA,0, 0,SSL_aECDSA,0,0,0,0,0,0,0}, {0,SSL_TXT_ECDSA,0, 0,SSL_aECDSA, 0,0,0,0,0,0,0}, - {0,SSL_TXT_aPSK,0, 0,SSL_aPSK, 0,0,0,0,0,0,0}, + {0,SSL_TXT_aPSK,0, 0,SSL_aPSK, 0,0,0,0,0,0,0}, {0,SSL_TXT_aGOST94,0,0,SSL_aGOST94,0,0,0,0,0,0,0}, {0,SSL_TXT_aGOST01,0,0,SSL_aGOST01,0,0,0,0,0,0,0}, {0,SSL_TXT_aGOST,0,0,SSL_aGOST94|SSL_aGOST01,0,0,0,0,0,0,0}, @@ -284,7 +285,8 @@ static const SSL_CIPHER cipher_aliases[]={ {0,SSL_TXT_RSA,0, SSL_kRSA,SSL_aRSA,0,0,0,0,0,0,0}, {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_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}, @@ -755,7 +757,7 @@ static void ssl_cipher_get_disabled(unsigned long *mkey, unsigned long *auth, un *auth |= SSL_aECDH; #endif #ifdef OPENSSL_NO_PSK - *mkey |= SSL_kPSK; + *mkey |= SSL_kPSK|SSL_kRSAPSK; *auth |= SSL_aPSK; #endif #ifdef OPENSSL_NO_SRP @@ -1535,7 +1537,8 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method, ssl_cipher_apply_rule(0, 0, SSL_aECDH, 0, 0, 0, 0, CIPHER_ORD, -1, &head, &tail); /* ssl_cipher_apply_rule(0, 0, SSL_aDH, 0, 0, 0, 0, CIPHER_ORD, -1, &head, &tail); */ ssl_cipher_apply_rule(0, SSL_kRSA, 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); + 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); ssl_cipher_apply_rule(0, SSL_kKRB5, 0,0, 0, 0, 0, CIPHER_ORD, -1, &head, &tail); /* RC4 is sort-of broken -- move the the end */ @@ -1717,6 +1720,9 @@ char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf, int len) case SSL_kGOST: kx="GOST"; break; + case SSL_kRSAPSK: + kx="RSAPSK"; + break; default: kx="unknown"; } diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index 43204de..6969672 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -2460,8 +2460,14 @@ void ssl_set_cert_masks(CERT *c, 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 1fd6bb1..2a5179b 100644 --- a/ssl/ssl_locl.h +++ b/ssl/ssl_locl.h @@ -301,6 +301,7 @@ #define SSL_kPSK 0x00000100L /* PSK */ #define SSL_kGOST 0x00000200L /* GOST key exchange */ #define SSL_kSRP 0x00000400L /* SRP */ +#define SSL_kRSAPSK 0x00000800L /* RSA-PSK */ /* Bits for algorithm_auth (server authentication) */ #define SSL_aRSA 0x00000001L /* RSA auth */ diff --git a/ssl/tls1.h b/ssl/tls1.h index e8188ec..1018c50 100644 --- a/ssl/tls1.h +++ b/ssl/tls1.h @@ -416,6 +416,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 + /* Additional TLS ciphersuites from expired Internet Draft * draft-ietf-tls-56-bit-ciphersuites-01.txt * (available if TLS1_ALLOW_EXPERIMENTAL_CIPHERSUITES is defined, see @@ -655,6 +673,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 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 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 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" -- 1.7.9.5
smime.p7s
Description: S/MIME cryptographic signature