RFC4507 (including RFC4507bis) TLS stateless session resumption support
[oweals/openssl.git] / ssl / s3_enc.c
index 6d92050bb17b270b1c8dcc21d86f84cbba09dd45..010069bf28a570daf873989dec9bf76f51000192 100644 (file)
@@ -56,7 +56,7 @@
  * [including the GNU Public Licence.]
  */
 /* ====================================================================
- * Copyright (c) 1998-2002 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * Hudson (tjh@cryptsoft.com).
  *
  */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
 
 #include <stdio.h>
 #include "ssl_locl.h"
@@ -196,7 +222,9 @@ int ssl3_change_cipher_state(SSL *s, int which)
        unsigned char *ms,*key,*iv,*er1,*er2;
        EVP_CIPHER_CTX *dd;
        const EVP_CIPHER *c;
+#ifndef OPENSSL_NO_COMP
        COMP_METHOD *comp;
+#endif
        const EVP_MD *m;
        EVP_MD_CTX md;
        int is_exp,n,i,j,k,cl;
@@ -205,10 +233,12 @@ int ssl3_change_cipher_state(SSL *s, int which)
        is_exp=SSL_C_IS_EXPORT(s->s3->tmp.new_cipher);
        c=s->s3->tmp.new_sym_enc;
        m=s->s3->tmp.new_hash;
+#ifndef OPENSSL_NO_COMP
        if (s->s3->tmp.new_compression == NULL)
                comp=NULL;
        else
                comp=s->s3->tmp.new_compression->method;
+#endif
        key_block=s->s3->tmp.key_block;
 
        if (which & SSL3_CC_READ)
@@ -217,8 +247,13 @@ int ssl3_change_cipher_state(SSL *s, int which)
                        reuse_dd = 1;
                else if ((s->enc_read_ctx=OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL)
                        goto err;
+               else
+                       /* make sure it's intialized in case we exit later with an error */
+                       EVP_CIPHER_CTX_init(s->enc_read_ctx);
                dd= s->enc_read_ctx;
-               s->read_hash=m;
+
+               ssl_replace_hash(&s->read_hash,m);
+#ifndef OPENSSL_NO_COMP
                /* COMPRESS */
                if (s->expand != NULL)
                        {
@@ -239,6 +274,7 @@ int ssl3_change_cipher_state(SSL *s, int which)
                        if (s->s3->rrec.comp == NULL)
                                goto err;
                        }
+#endif
                memset(&(s->s3->read_sequence[0]),0,8);
                mac_secret= &(s->s3->read_mac_secret[0]);
                }
@@ -248,8 +284,12 @@ int ssl3_change_cipher_state(SSL *s, int which)
                        reuse_dd = 1;
                else if ((s->enc_write_ctx=OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL)
                        goto err;
+               else
+                       /* make sure it's intialized in case we exit later with an error */
+                       EVP_CIPHER_CTX_init(s->enc_write_ctx);
                dd= s->enc_write_ctx;
-               s->write_hash=m;
+               ssl_replace_hash(&s->write_hash,m);
+#ifndef OPENSSL_NO_COMP
                /* COMPRESS */
                if (s->compress != NULL)
                        {
@@ -265,13 +305,13 @@ int ssl3_change_cipher_state(SSL *s, int which)
                                goto err2;
                                }
                        }
+#endif
                memset(&(s->s3->write_sequence[0]),0,8);
                mac_secret= &(s->s3->write_mac_secret[0]);
                }
 
        if (reuse_dd)
                EVP_CIPHER_CTX_cleanup(dd);
-       EVP_CIPHER_CTX_init(dd);
 
        p=s->s3->tmp.key_block;
        i=EVP_MD_size(m);
@@ -355,7 +395,7 @@ int ssl3_setup_key_block(SSL *s)
        if (s->s3->tmp.key_block_length != 0)
                return(1);
 
-       if (!ssl_cipher_get_evp(s->session,&c,&hash,&comp))
+       if (!ssl_cipher_get_evp(s->session,&c,&hash,NULL,NULL,&comp))
                {
                SSLerr(SSL_F_SSL3_SETUP_KEY_BLOCK,SSL_R_CIPHER_OR_HASH_UNAVAILABLE);
                return(0);
@@ -363,7 +403,11 @@ int ssl3_setup_key_block(SSL *s)
 
        s->s3->tmp.new_sym_enc=c;
        s->s3->tmp.new_hash=hash;
+#ifdef OPENSSL_NO_COMP
+       s->s3->tmp.new_compression=NULL;
+#else
        s->s3->tmp.new_compression=comp;
+#endif
 
        num=EVP_CIPHER_key_length(c)+EVP_MD_size(hash)+EVP_CIPHER_iv_length(c);
        num*=2;
@@ -387,11 +431,11 @@ int ssl3_setup_key_block(SSL *s)
 
                if (s->session->cipher != NULL)
                        {
-                       if ((s->session->cipher->algorithms & SSL_ENC_MASK) == SSL_eNULL)
+                       if (s->session->cipher->algorithm_enc == SSL_eNULL)
                                s->s3->need_empty_fragments = 0;
                        
 #ifndef OPENSSL_NO_RC4
-                       if ((s->session->cipher->algorithms & SSL_ENC_MASK) == SSL_RC4)
+                       if (s->session->cipher->algorithm_enc == SSL_RC4)
                                s->s3->need_empty_fragments = 0;
 #endif
                        }
@@ -538,7 +582,6 @@ static int ssl3_handshake_mac(SSL *s, EVP_MD_CTX *in_ctx,
 
        EVP_MD_CTX_init(&ctx);
        EVP_MD_CTX_copy_ex(&ctx,in_ctx);
-
        n=EVP_MD_CTX_size(&ctx);
        npad=(48/n)*n;
 
@@ -566,7 +609,7 @@ int ssl3_mac(SSL *ssl, unsigned char *md, int send)
        SSL3_RECORD *rec;
        unsigned char *mac_sec,*seq;
        EVP_MD_CTX md_ctx;
-       const EVP_MD *hash;
+       const EVP_MD_CTX *hash;
        unsigned char *p,rec_char;
        unsigned int md_size;
        int npad;
@@ -586,13 +629,13 @@ int ssl3_mac(SSL *ssl, unsigned char *md, int send)
                hash=ssl->read_hash;
                }
 
-       md_size=EVP_MD_size(hash);
+       md_size=EVP_MD_CTX_size(hash);
        npad=(48/md_size)*md_size;
 
        /* Chop the digest off the end :-) */
        EVP_MD_CTX_init(&md_ctx);
 
-       EVP_DigestInit_ex(  &md_ctx,hash, NULL);
+       EVP_MD_CTX_copy_ex( &md_ctx,hash);
        EVP_DigestUpdate(&md_ctx,mac_sec,md_size);
        EVP_DigestUpdate(&md_ctx,ssl3_pad_1,npad);
        EVP_DigestUpdate(&md_ctx,seq,8);
@@ -604,7 +647,7 @@ int ssl3_mac(SSL *ssl, unsigned char *md, int send)
        EVP_DigestUpdate(&md_ctx,rec->input,rec->length);
        EVP_DigestFinal_ex( &md_ctx,md,NULL);
 
-       EVP_DigestInit_ex(  &md_ctx,hash, NULL);
+       EVP_MD_CTX_copy_ex( &md_ctx,hash);
        EVP_DigestUpdate(&md_ctx,mac_sec,md_size);
        EVP_DigestUpdate(&md_ctx,ssl3_pad_2,npad);
        EVP_DigestUpdate(&md_ctx,md,md_size);
@@ -697,6 +740,12 @@ int ssl3_alert_code(int code)
        case SSL_AD_INTERNAL_ERROR:     return(SSL3_AD_HANDSHAKE_FAILURE);
        case SSL_AD_USER_CANCELLED:     return(SSL3_AD_HANDSHAKE_FAILURE);
        case SSL_AD_NO_RENEGOTIATION:   return(-1); /* Don't send it :-) */
+       case SSL_AD_UNSUPPORTED_EXTENSION: return(SSL3_AD_HANDSHAKE_FAILURE);
+       case SSL_AD_CERTIFICATE_UNOBTAINABLE: return(SSL3_AD_HANDSHAKE_FAILURE);
+       case SSL_AD_UNRECOGNIZED_NAME:  return(SSL3_AD_HANDSHAKE_FAILURE);
+       case SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE: return(SSL3_AD_HANDSHAKE_FAILURE);
+       case SSL_AD_BAD_CERTIFICATE_HASH_VALUE: return(SSL3_AD_HANDSHAKE_FAILURE);
+       case SSL_AD_UNKNOWN_PSK_IDENTITY:return(TLS1_AD_UNKNOWN_PSK_IDENTITY);
        default:                        return(-1);
                }
        }