Get correct GOST private key instead of just assuming the last one is
[openssl.git] / ssl / s3_srvr.c
index 92f73b668102828da9d3dfea2f977a4f7159c494..49751a00487eaa72e0a4de2bf055016148f68e6f 100644 (file)
@@ -218,7 +218,7 @@ int ssl3_accept(SSL *s)
                switch (s->state)
                        {
                case SSL_ST_RENEGOTIATE:
-                       s->new_session=1;
+                       s->renegotiate=1;
                        /* s->state=SSL_ST_ACCEPT; */
 
                case SSL_ST_BEFORE:
@@ -316,7 +316,7 @@ int ssl3_accept(SSL *s)
                        ret=ssl3_get_client_hello(s);
                        if (ret <= 0) goto end;
                        
-                       s->new_session = 2;
+                       s->renegotiate = 2;
                        s->state=SSL3_ST_SW_SRVR_HELLO_A;
                        s->init_num=0;
                        break;
@@ -538,7 +538,14 @@ int ssl3_accept(SSL *s)
                                 * the client uses its key from the certificate
                                 * for key exchange.
                                 */
+#if defined(OPENSSL_NO_TLSEXT) || defined(OPENSSL_NO_NEXTPROTONEG)
                                s->state=SSL3_ST_SR_FINISHED_A;
+#else
+                               if (s->s3->next_proto_neg_seen)
+                                       s->state=SSL3_ST_SR_NEXT_PROTO_A;
+                               else
+                                       s->state=SSL3_ST_SR_FINISHED_A;
+#endif
                                s->init_num = 0;
                                }
                        else
@@ -581,10 +588,27 @@ int ssl3_accept(SSL *s)
                        ret=ssl3_get_cert_verify(s);
                        if (ret <= 0) goto end;
 
+#if defined(OPENSSL_NO_TLSEXT) || defined(OPENSSL_NO_NEXTPROTONEG)
                        s->state=SSL3_ST_SR_FINISHED_A;
+#else
+                       if (s->s3->next_proto_neg_seen)
+                               s->state=SSL3_ST_SR_NEXT_PROTO_A;
+                       else
+                               s->state=SSL3_ST_SR_FINISHED_A;
+#endif
                        s->init_num=0;
                        break;
 
+#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
+               case SSL3_ST_SR_NEXT_PROTO_A:
+               case SSL3_ST_SR_NEXT_PROTO_B:
+                       ret=ssl3_get_next_proto(s);
+                       if (ret <= 0) goto end;
+                       s->init_num = 0;
+                       s->state=SSL3_ST_SR_FINISHED_A;
+                       break;
+#endif
+
                case SSL3_ST_SR_FINISHED_A:
                case SSL3_ST_SR_FINISHED_B:
                        ret=ssl3_get_finished(s,SSL3_ST_SR_FINISHED_A,
@@ -655,7 +679,16 @@ int ssl3_accept(SSL *s)
                        if (ret <= 0) goto end;
                        s->state=SSL3_ST_SW_FLUSH;
                        if (s->hit)
+                               {
+#if defined(OPENSSL_NO_TLSEXT) || defined(OPENSSL_NO_NEXTPROTONEG)
                                s->s3->tmp.next_state=SSL3_ST_SR_FINISHED_A;
+#else
+                               if (s->s3->next_proto_neg_seen)
+                                       s->s3->tmp.next_state=SSL3_ST_SR_NEXT_PROTO_A;
+                               else
+                                       s->s3->tmp.next_state=SSL3_ST_SR_FINISHED_A;
+#endif
+                               }
                        else
                                s->s3->tmp.next_state=SSL_ST_OK;
                        s->init_num=0;
@@ -673,11 +706,12 @@ int ssl3_accept(SSL *s)
 
                        s->init_num=0;
 
-                       if (s->new_session == 2) /* skipped if we just sent a HelloRequest */
+                       if (s->renegotiate == 2) /* skipped if we just sent a HelloRequest */
                                {
                                /* actually not necessarily a 'new' session unless
                                 * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is set */
                                
+                               s->renegotiate=0;
                                s->new_session=0;
                                
                                ssl_update_cache(s,SSL_SESS_CACHE_SERVER);
@@ -1217,6 +1251,13 @@ int ssl3_get_client_hello(SSL *s)
                        goto f_err;
                        }
                s->s3->tmp.new_cipher=c;
+               /* check whether we should disable session resumption */
+               if (s->not_resumable_session_cb != NULL)
+                       s->session->not_resumable=s->not_resumable_session_cb(s,
+                               ((c->algorithm_mkey & (SSL_kEDH | SSL_kEECDH)) != 0));
+               if (s->session->not_resumable)
+                       /* do not send a session ticket */
+                       s->tlsext_ticket_expected = 0;
                }
        else
                {
@@ -1320,8 +1361,9 @@ int ssl3_send_server_hello(SSL *s)
                 * if session caching is disabled so existing functionality
                 * is unaffected.
                 */
-               if (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER)
-                       && !s->hit)
+               if (s->session->not_resumable ||
+                       (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER)
+                               && !s->hit))
                        s->session->session_id_length=0;
 
                sl=s->session->session_id_length;
@@ -2579,12 +2621,19 @@ int ssl3_get_client_key_exchange(SSL *s)
                        {
                        int ret = 0;
                        EVP_PKEY_CTX *pkey_ctx;
-                       EVP_PKEY *client_pub_pkey = NULL;
+                       EVP_PKEY *client_pub_pkey = NULL, *pk = NULL;
                        unsigned char premaster_secret[32], *start;
-                       size_t outlen=32, inlen;                        
+                       size_t outlen=32, inlen;
+                       unsigned long alg_a;
 
                        /* Get our certificate private key*/
-                       pkey_ctx = EVP_PKEY_CTX_new(s->cert->key->privatekey,NULL);     
+                       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
@@ -3177,4 +3226,72 @@ int ssl3_send_cert_status(SSL *s)
        /* SSL3_ST_SW_CERT_STATUS_B */
        return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
        }
+
+# ifndef OPENSSL_NO_NPN
+/* ssl3_get_next_proto reads a Next Protocol Negotiation handshake message. It
+ * sets the next_proto member in s if found */
+int ssl3_get_next_proto(SSL *s)
+       {
+       int ok;
+       int proto_len, padding_len;
+       long n;
+       const unsigned char *p;
+
+       /* Clients cannot send a NextProtocol message if we didn't see the
+        * extension in their ClientHello */
+       if (!s->s3->next_proto_neg_seen)
+               {
+               SSLerr(SSL_F_SSL3_GET_NEXT_PROTO,SSL_R_GOT_NEXT_PROTO_WITHOUT_EXTENSION);
+               return -1;
+               }
+
+       n=s->method->ssl_get_message(s,
+               SSL3_ST_SR_NEXT_PROTO_A,
+               SSL3_ST_SR_NEXT_PROTO_B,
+               SSL3_MT_NEXT_PROTO,
+               514,  /* See the payload format below */
+               &ok);
+
+       if (!ok)
+               return((int)n);
+
+       /* s->state doesn't reflect whether ChangeCipherSpec has been received
+        * in this handshake, but s->s3->change_cipher_spec does (will be reset
+        * by ssl3_get_finished). */
+       if (!s->s3->change_cipher_spec)
+               {
+               SSLerr(SSL_F_SSL3_GET_NEXT_PROTO,SSL_R_GOT_NEXT_PROTO_BEFORE_A_CCS);
+               return -1;
+               }
+
+       if (n < 2)
+               return 0;  /* The body must be > 1 bytes long */
+
+       p=(unsigned char *)s->init_msg;
+
+       /* The payload looks like:
+        *   uint8 proto_len;
+        *   uint8 proto[proto_len];
+        *   uint8 padding_len;
+        *   uint8 padding[padding_len];
+        */
+       proto_len = p[0];
+       if (proto_len + 2 > s->init_num)
+               return 0;
+       padding_len = p[proto_len + 1];
+       if (proto_len + padding_len + 2 != s->init_num)
+               return 0;
+
+       s->next_proto_negotiated = OPENSSL_malloc(proto_len);
+       if (!s->next_proto_negotiated)
+               {
+               SSLerr(SSL_F_SSL3_GET_NEXT_PROTO,ERR_R_MALLOC_FAILURE);
+               return 0;
+               }
+       memcpy(s->next_proto_negotiated, p + 1, proto_len);
+       s->next_proto_negotiated_len = proto_len;
+
+       return 1;
+       }
+# endif
 #endif