Don't round up partitioned premaster secret length if there is only one
[openssl.git] / ssl / t1_enc.c
index 5446bb250dd66308d36f8ae2f3e19b1ed00b7fb8..d180bfc95c4ba094f84223b1af8864cdd17c1a99 100644 (file)
@@ -159,68 +159,75 @@ static int tls1_P_hash(const EVP_MD *md, const unsigned char *sec,
                        unsigned char *out, int olen)
        {
        int chunk;
-       unsigned int j;
-       HMAC_CTX ctx;
-       HMAC_CTX ctx_tmp;
+       size_t j;
+       EVP_MD_CTX ctx, ctx_tmp;
+       EVP_PKEY *mac_key;
        unsigned char A1[EVP_MAX_MD_SIZE];
-       unsigned int A1_len;
+       size_t A1_len;
        int ret = 0;
        
        chunk=EVP_MD_size(md);
        OPENSSL_assert(chunk >= 0);
 
-       HMAC_CTX_init(&ctx);
-       HMAC_CTX_init(&ctx_tmp);
-       if (!HMAC_Init_ex(&ctx,sec,sec_len,md, NULL))
+       EVP_MD_CTX_init(&ctx);
+       EVP_MD_CTX_init(&ctx_tmp);
+       EVP_MD_CTX_set_flags(&ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
+       EVP_MD_CTX_set_flags(&ctx_tmp, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
+       mac_key = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, sec, sec_len);
+       if (!mac_key)
                goto err;
-       if (!HMAC_Init_ex(&ctx_tmp,sec,sec_len,md, NULL))
+       if (!EVP_DigestSignInit(&ctx,NULL,md, NULL, mac_key))
                goto err;
-       if (seed1 != NULL && !HMAC_Update(&ctx,seed1,seed1_len))
+       if (!EVP_DigestSignInit(&ctx_tmp,NULL,md, NULL, mac_key))
                goto err;
-       if (seed2 != NULL && !HMAC_Update(&ctx,seed2,seed2_len))
+       if (seed1 && !EVP_DigestSignUpdate(&ctx,seed1,seed1_len))
                goto err;
-       if (seed3 != NULL && !HMAC_Update(&ctx,seed3,seed3_len))
+       if (seed2 && !EVP_DigestSignUpdate(&ctx,seed2,seed2_len))
                goto err;
-       if (seed4 != NULL && !HMAC_Update(&ctx,seed4,seed4_len))
+       if (seed3 && !EVP_DigestSignUpdate(&ctx,seed3,seed3_len))
                goto err;
-       if (seed5 != NULL && !HMAC_Update(&ctx,seed5,seed5_len))
+       if (seed4 && !EVP_DigestSignUpdate(&ctx,seed4,seed4_len))
                goto err;
-       if (!HMAC_Final(&ctx,A1,&A1_len))
+       if (seed5 && !EVP_DigestSignUpdate(&ctx,seed5,seed5_len))
+               goto err;
+       if (!EVP_DigestSignFinal(&ctx,A1,&A1_len))
                goto err;
 
        for (;;)
                {
-               if (!HMAC_Init_ex(&ctx,NULL,0,NULL,NULL)) /* re-init */
+               /* Reinit mac contexts */
+               if (!EVP_DigestSignInit(&ctx,NULL,md, NULL, mac_key))
                        goto err;
-               if (!HMAC_Init_ex(&ctx_tmp,NULL,0,NULL,NULL)) /* re-init */
+               if (!EVP_DigestSignInit(&ctx_tmp,NULL,md, NULL, mac_key))
                        goto err;
-               if (!HMAC_Update(&ctx,A1,A1_len))
+               if (!EVP_DigestSignUpdate(&ctx,A1,A1_len))
                        goto err;
-               if (!HMAC_Update(&ctx_tmp,A1,A1_len))
+               if (!EVP_DigestSignUpdate(&ctx_tmp,A1,A1_len))
                        goto err;
-               if (seed1 != NULL && !HMAC_Update(&ctx,seed1,seed1_len))
+               if (seed1 && !EVP_DigestSignUpdate(&ctx,seed1,seed1_len))
                        goto err;
-               if (seed2 != NULL && !HMAC_Update(&ctx,seed2,seed2_len))
+               if (seed2 && !EVP_DigestSignUpdate(&ctx,seed2,seed2_len))
                        goto err;
-               if (seed3 != NULL && !HMAC_Update(&ctx,seed3,seed3_len))
+               if (seed3 && !EVP_DigestSignUpdate(&ctx,seed3,seed3_len))
                        goto err;
-               if (seed4 != NULL && !HMAC_Update(&ctx,seed4,seed4_len))
+               if (seed4 && !EVP_DigestSignUpdate(&ctx,seed4,seed4_len))
                        goto err;
-               if (seed5 != NULL && !HMAC_Update(&ctx,seed5,seed5_len))
+               if (seed5 && !EVP_DigestSignUpdate(&ctx,seed5,seed5_len))
                        goto err;
 
                if (olen > chunk)
                        {
-                       if (!HMAC_Final(&ctx,out,&j))
+                       if (!EVP_DigestSignFinal(&ctx,out,&j))
                                goto err;
                        out+=j;
                        olen-=j;
-                       if (!HMAC_Final(&ctx_tmp,A1,&A1_len)) /* calc the next A1 value */
+                       /* calc the next A1 value */
+                       if (!EVP_DigestSignFinal(&ctx_tmp,A1,&A1_len))
                                goto err;
                        }
                else    /* last one */
                        {
-                       if (!HMAC_Final(&ctx,A1,&A1_len))
+                       if (!EVP_DigestSignFinal(&ctx,A1,&A1_len))
                                goto err;
                        memcpy(out,A1,olen);
                        break;
@@ -228,8 +235,9 @@ static int tls1_P_hash(const EVP_MD *md, const unsigned char *sec,
                }
        ret = 1;
 err:
-       HMAC_CTX_cleanup(&ctx);
-       HMAC_CTX_cleanup(&ctx_tmp);
+       EVP_PKEY_free(mac_key);
+       EVP_MD_CTX_cleanup(&ctx);
+       EVP_MD_CTX_cleanup(&ctx_tmp);
        OPENSSL_cleanse(A1,sizeof(A1));
        return ret;
        }
@@ -257,6 +265,8 @@ static int tls1_PRF(long digest_mask,
                if ((m<<TLS1_PRF_DGST_SHIFT) & digest_mask) count++;
        }       
        len=slen/count;
+       if (count == 1)
+               slen = 0;
        S1=sec;
        memset(out1,0,olen);
        for (idx=0;ssl_get_handshake_digest(idx,&m,&md);idx++) {
@@ -285,7 +295,7 @@ static int tls1_generate_key_block(SSL *s, unsigned char *km,
             unsigned char *tmp, int num)
        {
        int ret;
-       ret = tls1_PRF(s->s3->tmp.new_cipher->algorithm2,
+       ret = tls1_PRF(ssl_get_algorithm2(s),
                 TLS_MD_KEY_EXPANSION_CONST,TLS_MD_KEY_EXPANSION_CONST_SIZE,
                 s->s3->server_random,SSL3_RANDOM_SIZE,
                 s->s3->client_random,SSL3_RANDOM_SIZE,
@@ -488,7 +498,7 @@ printf("which = %04X\nmac key=",which);
                /* In here I set both the read and write key/iv to the
                 * same value since only the correct one will be used :-).
                 */
-               if (!tls1_PRF(s->s3->tmp.new_cipher->algorithm2,
+               if (!tls1_PRF(ssl_get_algorithm2(s),
                                exp_label,exp_label_len,
                                s->s3->client_random,SSL3_RANDOM_SIZE,
                                s->s3->server_random,SSL3_RANDOM_SIZE,
@@ -499,7 +509,7 @@ printf("which = %04X\nmac key=",which);
 
                if (k > 0)
                        {
-                       if (!tls1_PRF(s->s3->tmp.new_cipher->algorithm2,
+                       if (!tls1_PRF(ssl_get_algorithm2(s),
                                        TLS_MD_IV_BLOCK_CONST,TLS_MD_IV_BLOCK_CONST_SIZE,
                                        s->s3->client_random,SSL3_RANDOM_SIZE,
                                        s->s3->server_random,SSL3_RANDOM_SIZE,
@@ -661,7 +671,8 @@ int tls1_enc(SSL *s, int send)
                        int ivlen;
                        enc=EVP_CIPHER_CTX_cipher(s->enc_write_ctx);
                        /* For TLSv1.1 and later explicit IV */
-                       if (s->version >= TLS1_1_VERSION)
+                       if (s->version >= TLS1_1_VERSION
+                               && EVP_CIPHER_mode(enc) == EVP_CIPH_CBC_MODE)
                                ivlen = EVP_CIPHER_iv_length(enc);
                        else
                                ivlen = 0;
@@ -750,6 +761,8 @@ int tls1_enc(SSL *s, int send)
                        {
                        if (l == 0 || l%bs != 0)
                                {
+                               if (s->version >= TLS1_1_VERSION)
+                                       return -1;
                                SSLerr(SSL_F_TLS1_ENC,SSL_R_BLOCK_CIPHER_PAD_IS_WRONG);
                                ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECRYPTION_FAILED);
                                return 0;
@@ -807,7 +820,8 @@ int tls1_enc(SSL *s, int send)
                                        }
                                }
                        rec->length -=i;
-                       if (s->version >= TLS1_1_VERSION)
+                       if (s->version >= TLS1_1_VERSION
+                               && EVP_CIPHER_CTX_mode(ds) == EVP_CIPH_CBC_MODE)
                                {
                                rec->data += bs;    /* skip the explicit IV */
                                rec->input += bs;
@@ -869,7 +883,7 @@ int tls1_final_finish_mac(SSL *s,
 
        for (idx=0;ssl_get_handshake_digest(idx,&mask,&md);idx++)
                {
-               if (mask & s->s3->tmp.new_cipher->algorithm2)
+               if (mask & ssl_get_algorithm2(s))
                        {
                        int hashsize = EVP_MD_size(md);
                        if (hashsize < 0 || hashsize > (int)(sizeof buf - (size_t)(q-buf)))
@@ -888,7 +902,7 @@ int tls1_final_finish_mac(SSL *s,
                        }
                }
                
-       if (!tls1_PRF(s->s3->tmp.new_cipher->algorithm2,
+       if (!tls1_PRF(ssl_get_algorithm2(s),
                        str,slen, buf,(int)(q-buf), NULL,0, NULL,0, NULL,0,
                        s->session->master_key,s->session->master_key_length,
                        out,buf2,sizeof buf2))
@@ -998,6 +1012,7 @@ int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
        const void *co = NULL, *so = NULL;
        int col = 0, sol = 0;
 
+
 #ifdef KSSL_DEBUG
        printf ("tls1_generate_master_secret(%p,%p, %p, %d)\n", s,out, p,len);
 #endif /* KSSL_DEBUG */
@@ -1014,7 +1029,7 @@ int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
                }
 #endif
 
-       tls1_PRF(s->s3->tmp.new_cipher->algorithm2,
+       tls1_PRF(ssl_get_algorithm2(s),
                TLS_MD_MASTER_SECRET_CONST,TLS_MD_MASTER_SECRET_CONST_SIZE,
                s->s3->client_random,SSL3_RANDOM_SIZE,
                co, col,
@@ -1022,6 +1037,16 @@ int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
                so, sol,
                p,len,
                s->session->master_key,buff,sizeof buff);
+#ifdef SSL_DEBUG
+       fprintf(stderr, "Premaster Secret:\n");
+       BIO_dump_fp(stderr, (char *)p, len);
+       fprintf(stderr, "Client Random:\n");
+       BIO_dump_fp(stderr, (char *)s->s3->client_random, SSL3_RANDOM_SIZE);
+       fprintf(stderr, "Server Random:\n");
+       BIO_dump_fp(stderr, (char *)s->s3->server_random, SSL3_RANDOM_SIZE);
+       fprintf(stderr, "Master Secret:\n");
+       BIO_dump_fp(stderr, (char *)s->session->master_key, SSL3_MASTER_SECRET_SIZE);
+#endif
 
 #ifdef KSSL_DEBUG
        printf ("tls1_generate_master_secret() complete\n");
@@ -1063,6 +1088,9 @@ int tls1_alert_code(int code)
        case SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE: return(TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE);
        case SSL_AD_BAD_CERTIFICATE_HASH_VALUE: return(TLS1_AD_BAD_CERTIFICATE_HASH_VALUE);
        case SSL_AD_UNKNOWN_PSK_IDENTITY:return(TLS1_AD_UNKNOWN_PSK_IDENTITY);
+#ifndef OPENSSL_NO_SRP
+       case SSL_AD_MISSING_SRP_USERNAME:return(TLS1_AD_MISSING_SRP_USERNAME);
+#endif
 #if 0 /* not appropriate for TLS, not used for DTLS */
        case DTLS1_AD_MISSING_HANDSHAKE_MESSAGE: return 
                                          (DTLS1_AD_MISSING_HANDSHAKE_MESSAGE);
@@ -1071,3 +1099,26 @@ int tls1_alert_code(int code)
                }
        }
 
+int SSL_tls1_key_exporter(SSL *s, unsigned char *label, int label_len,
+                           unsigned char *context, int context_len,
+                           unsigned char *out, int olen)
+       {
+       unsigned char *tmp;
+       int rv;
+
+       tmp = OPENSSL_malloc(olen);
+
+       if (!tmp)
+               return 0;
+       
+       rv = tls1_PRF(ssl_get_algorithm2(s),
+                        label, label_len,
+                        s->s3->client_random,SSL3_RANDOM_SIZE,
+                        s->s3->server_random,SSL3_RANDOM_SIZE,
+                        context, context_len, NULL, 0,
+                        s->session->master_key, s->session->master_key_length,
+                        out, tmp, olen);
+
+       OPENSSL_free(tmp);
+       return rv;
+       }