+ printf("which = %04X\nmac key=", which);
+ {
+ int z;
+ for (z = 0; z < i; z++)
+ printf("%02X%c", ms[z], ((z + 1) % 16) ? ' ' : '\n');
+ }
+#endif
+ if (is_export) {
+ /*
+ * 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(ssl_get_algorithm2(s),
+ exp_label, exp_label_len,
+ s->s3->client_random, SSL3_RANDOM_SIZE,
+ s->s3->server_random, SSL3_RANDOM_SIZE,
+ NULL, 0, NULL, 0,
+ key, j, tmp1, tmp2, EVP_CIPHER_key_length(c)))
+ goto err2;
+ key = tmp1;
+
+ if (k > 0) {
+ 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,
+ NULL, 0, NULL, 0, empty, 0, iv1, iv2, k * 2))
+ goto err2;
+ if (client_write)
+ iv = iv1;
+ else
+ iv = &(iv1[k]);
+ }
+ }
+
+ if (EVP_CIPHER_mode(c) == EVP_CIPH_GCM_MODE) {
+ if (!EVP_CipherInit_ex(dd, c, NULL, key, NULL, (which & SSL3_CC_WRITE))
+ || !EVP_CIPHER_CTX_ctrl(dd, EVP_CTRL_GCM_SET_IV_FIXED, k, iv)) {
+ SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
+ goto err2;
+ }
+ } else if (EVP_CIPHER_mode(c) == EVP_CIPH_CCM_MODE) {
+ int taglen;
+ if (s->s3->tmp.new_cipher->algorithm_enc & (SSL_AES128CCM8|SSL_AES256CCM8))
+ taglen = 8;
+ else
+ taglen = 16;
+ if (!EVP_CipherInit_ex(dd, c, NULL, NULL, NULL, (which & SSL3_CC_WRITE))
+ || !EVP_CIPHER_CTX_ctrl(dd, EVP_CTRL_AEAD_SET_IVLEN, 12, NULL)
+ || !EVP_CIPHER_CTX_ctrl(dd, EVP_CTRL_AEAD_SET_TAG, taglen, NULL)
+ || !EVP_CIPHER_CTX_ctrl(dd, EVP_CTRL_CCM_SET_IV_FIXED, k, iv)
+ || !EVP_CipherInit_ex(dd, NULL, NULL, key, NULL, -1)) {
+ SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
+ goto err2;
+ }
+ } else {
+ if (!EVP_CipherInit_ex(dd, c, NULL, key, iv, (which & SSL3_CC_WRITE))) {
+ SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
+ goto err2;
+ }
+ }
+ /* Needed for "composite" AEADs, such as RC4-HMAC-MD5 */
+ if ((EVP_CIPHER_flags(c) & EVP_CIPH_FLAG_AEAD_CIPHER) && *mac_secret_size
+ && !EVP_CIPHER_CTX_ctrl(dd, EVP_CTRL_AEAD_SET_MAC_KEY,
+ *mac_secret_size, mac_secret)) {
+ SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
+ goto err2;
+ }
+#ifdef OPENSSL_SSL_TRACE_CRYPTO
+ if (s->msg_callback) {
+ int wh = which & SSL3_CC_WRITE ? TLS1_RT_CRYPTO_WRITE : 0;
+ if (*mac_secret_size)
+ s->msg_callback(2, s->version, wh | TLS1_RT_CRYPTO_MAC,
+ mac_secret, *mac_secret_size,
+ s, s->msg_callback_arg);
+ if (c->key_len)
+ s->msg_callback(2, s->version, wh | TLS1_RT_CRYPTO_KEY,
+ key, c->key_len, s, s->msg_callback_arg);
+ if (k) {
+ if (EVP_CIPHER_mode(c) == EVP_CIPH_GCM_MODE)
+ wh |= TLS1_RT_CRYPTO_FIXED_IV;
+ else
+ wh |= TLS1_RT_CRYPTO_IV;
+ s->msg_callback(2, s->version, wh, iv, k, s, s->msg_callback_arg);
+ }
+ }