PKCS#8 support for alternative PRFs.
[openssl.git] / ssl / t1_enc.c
index 4e23bbf77b4e26c56ccd3d3a14aad3817cc738bb..a98f6fe882d7362d76e2fe273a7e4ccefd16b748 100644 (file)
@@ -160,7 +160,7 @@ static int tls1_P_hash(const EVP_MD *md, const unsigned char *sec,
        {
        int chunk;
        size_t j;
-       EVP_MD_CTX ctx, ctx_tmp;
+       EVP_MD_CTX ctx, ctx_tmp, ctx_init;
        EVP_PKEY *mac_key;
        unsigned char A1[EVP_MAX_MD_SIZE];
        size_t A1_len;
@@ -171,14 +171,14 @@ static int tls1_P_hash(const EVP_MD *md, const unsigned char *sec,
 
        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);
+       EVP_MD_CTX_init(&ctx_init);
+       EVP_MD_CTX_set_flags(&ctx_init, 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 (!EVP_DigestSignInit(&ctx,NULL,md, NULL, mac_key))
+       if (!EVP_DigestSignInit(&ctx_init,NULL,md, NULL, mac_key))
                goto err;
-       if (!EVP_DigestSignInit(&ctx_tmp,NULL,md, NULL, mac_key))
+       if (!EVP_MD_CTX_copy_ex(&ctx,&ctx_init))
                goto err;
        if (seed1 && !EVP_DigestSignUpdate(&ctx,seed1,seed1_len))
                goto err;
@@ -196,13 +196,11 @@ static int tls1_P_hash(const EVP_MD *md, const unsigned char *sec,
        for (;;)
                {
                /* Reinit mac contexts */
-               if (!EVP_DigestSignInit(&ctx,NULL,md, NULL, mac_key))
-                       goto err;
-               if (!EVP_DigestSignInit(&ctx_tmp,NULL,md, NULL, mac_key))
+               if (!EVP_MD_CTX_copy_ex(&ctx,&ctx_init))
                        goto err;
                if (!EVP_DigestSignUpdate(&ctx,A1,A1_len))
                        goto err;
-               if (!EVP_DigestSignUpdate(&ctx_tmp,A1,A1_len))
+               if (olen>chunk && !EVP_MD_CTX_copy_ex(&ctx_tmp,&ctx))
                        goto err;
                if (seed1 && !EVP_DigestSignUpdate(&ctx,seed1,seed1_len))
                        goto err;
@@ -238,6 +236,7 @@ err:
        EVP_PKEY_free(mac_key);
        EVP_MD_CTX_cleanup(&ctx);
        EVP_MD_CTX_cleanup(&ctx_tmp);
+       EVP_MD_CTX_cleanup(&ctx_init);
        OPENSSL_cleanse(A1,sizeof(A1));
        return ret;
        }
@@ -414,15 +413,20 @@ int tls1_change_cipher_state(SSL *s, int which)
                        s->mac_flags |= SSL_MAC_FLAG_WRITE_MAC_STREAM;
                        else
                        s->mac_flags &= ~SSL_MAC_FLAG_WRITE_MAC_STREAM;
-               if (s->enc_write_ctx != NULL)
+               if (s->enc_write_ctx != NULL && !SSL_IS_DTLS(s))
                        reuse_dd = 1;
-               else if ((s->enc_write_ctx=OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL)
+               else if ((s->enc_write_ctx=EVP_CIPHER_CTX_new()) == 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;
-               mac_ctx = ssl_replace_hash(&s->write_hash,NULL);
+               if (SSL_IS_DTLS(s))
+                       {
+                       mac_ctx = EVP_MD_CTX_create();
+                       if (!mac_ctx)
+                               goto err;
+                       s->write_hash = mac_ctx;
+                       }
+               else
+                       mac_ctx = ssl_replace_hash(&s->write_hash,NULL);
 #ifndef OPENSSL_NO_COMP
                if (s->compress != NULL)
                        {
@@ -616,7 +620,7 @@ int tls1_setup_key_block(SSL *s)
        if (s->s3->tmp.key_block_length != 0)
                return(1);
 
-       if (!ssl_cipher_get_evp(s->session,&c,&hash,&mac_type,&mac_secret_size,&comp))
+       if (!ssl_cipher_get_evp(s->session,&c,&hash,&mac_type,&mac_secret_size,&comp, SSL_USE_ETM(s)))
                {
                SSLerr(SSL_F_TLS1_SETUP_KEY_BLOCK,SSL_R_CIPHER_OR_HASH_UNAVAILABLE);
                return(0);
@@ -698,7 +702,7 @@ err:
  *       short etc).
  *   1: if the record's padding is valid / the encryption was successful.
  *   -1: if the record's padding/AEAD-authenticator is invalid or, if sending,
- *       an internal error occured.
+ *       an internal error occurred.
  */
 int tls1_enc(SSL *s, int send)
        {
@@ -724,7 +728,7 @@ 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 (SSL_USE_EXPLICIT_IV(s)
                                && EVP_CIPHER_mode(enc) == EVP_CIPH_CBC_MODE)
                                ivlen = EVP_CIPHER_iv_length(enc);
                        else
@@ -779,7 +783,7 @@ int tls1_enc(SSL *s, int send)
 
                        seq = send?s->s3->write_sequence:s->s3->read_sequence;
 
-                       if (s->version == DTLS1_VERSION || s->version == DTLS1_BAD_VER)
+                       if (SSL_IS_DTLS(s))
                                {
                                unsigned char dtlsseq[9],*p=dtlsseq;
 
@@ -874,7 +878,7 @@ int tls1_enc(SSL *s, int send)
 #endif /* KSSL_DEBUG */
 
                ret = 1;
-               if (EVP_MD_CTX_md(s->read_hash) != NULL)
+               if (!SSL_USE_ETM(s) && EVP_MD_CTX_md(s->read_hash) != NULL)
                        mac_size = EVP_MD_CTX_size(s->read_hash);
                if ((bs != 1) && !send)
                        ret = tls1_cbc_remove_padding(s, rec, bs, mac_size);
@@ -939,18 +943,19 @@ int tls1_final_finish_mac(SSL *s,
                if (mask & ssl_get_algorithm2(s))
                        {
                        int hashsize = EVP_MD_size(md);
-                       if (hashsize < 0 || hashsize > (int)(sizeof buf - (size_t)(q-buf)))
+                       EVP_MD_CTX *hdgst = s->s3->handshake_dgst[idx];
+                       if (!hdgst || hashsize < 0 || hashsize > (int)(sizeof buf - (size_t)(q-buf)))
                                {
                                /* internal error: 'buf' is too small for this cipersuite! */
                                err = 1;
                                }
                        else
                                {
-                               EVP_MD_CTX_copy_ex(&ctx,s->s3->handshake_dgst[idx]);
-                               EVP_DigestFinal_ex(&ctx,q,&i);
-                               if (i != (unsigned int)hashsize) /* can't really happen */
+                               if (!EVP_MD_CTX_copy_ex(&ctx, hdgst) ||
+                                       !EVP_DigestFinal_ex(&ctx,q,&i) ||
+                                       (i != (unsigned int)hashsize))
                                        err = 1;
-                               q+=i;
+                               q+=hashsize;
                                }
                        }
                }
@@ -973,7 +978,7 @@ int tls1_mac(SSL *ssl, unsigned char *md, int send)
        SSL3_RECORD *rec;
        unsigned char *seq;
        EVP_MD_CTX *hash;
-       size_t md_size, orig_len;
+       size_t md_size;
        int i;
        EVP_MD_CTX hmac, *mac_ctx;
        unsigned char header[13];
@@ -1004,11 +1009,12 @@ int tls1_mac(SSL *ssl, unsigned char *md, int send)
                }
                else
                {
-                       EVP_MD_CTX_copy(&hmac,hash);
+                       if (!EVP_MD_CTX_copy(&hmac,hash))
+                               return -1;
                        mac_ctx = &hmac;
                }
 
-       if (ssl->version == DTLS1_VERSION || ssl->version == DTLS1_BAD_VER)
+       if (SSL_IS_DTLS(ssl))
                {
                unsigned char dtlsseq[8],*p=dtlsseq;
 
@@ -1020,17 +1026,13 @@ int tls1_mac(SSL *ssl, unsigned char *md, int send)
        else
                memcpy(header, seq, 8);
 
-       /* kludge: tls1_cbc_remove_padding passes padding length in rec->type */
-       orig_len = rec->length+md_size+((unsigned int)rec->type>>8);
-       rec->type &= 0xff;
-
        header[8]=rec->type;
        header[9]=(unsigned char)(ssl->version>>8);
        header[10]=(unsigned char)(ssl->version);
        header[11]=(rec->length)>>8;
        header[12]=(rec->length)&0xff;
 
-       if (!send &&
+       if (!send && !SSL_USE_ETM(ssl) &&
            EVP_CIPHER_CTX_mode(ssl->enc_read_ctx) == EVP_CIPH_CBC_MODE &&
            ssl3_cbc_record_digest_supported(mac_ctx))
                {
@@ -1042,7 +1044,7 @@ int tls1_mac(SSL *ssl, unsigned char *md, int send)
                        mac_ctx,
                        md, &md_size,
                        header, rec->input,
-                       rec->length + md_size, orig_len,
+                       rec->length + md_size, rec->orig_len,
                        ssl->s3->read_mac_secret,
                        ssl->s3->read_mac_secret_size,
                        0 /* not SSLv3 */);
@@ -1054,11 +1056,11 @@ int tls1_mac(SSL *ssl, unsigned char *md, int send)
                t=EVP_DigestSignFinal(mac_ctx,md,&md_size);
                OPENSSL_assert(t > 0);
 #ifdef OPENSSL_FIPS
-               if (!send && FIPS_mode())
+               if (!send && !SSL_USE_ETM(ssl) && FIPS_mode())
                        tls_fips_digest_extra(
                                        ssl->enc_read_ctx,
                                        mac_ctx, rec->input,
-                                       rec->length, orig_len);
+                                       rec->length, rec->orig_len);
 #endif
                }
                
@@ -1075,7 +1077,7 @@ printf("rec=");
 {unsigned int z; for (z=0; z<rec->length; z++) printf("%02X ",buf[z]); printf("\n"); }
 #endif
 
-       if (ssl->version != DTLS1_VERSION && ssl->version != DTLS1_BAD_VER)
+       if (!SSL_IS_DTLS(ssl))
                {
                for (i=7; i>=0; i--)
                        {