OLD | NEW |
(Empty) | |
| 1 From d7f9af2d2682bc41e7bf1d669cda60f04630b04d Mon Sep 17 00:00:00 2001 |
| 2 From: Adam Langley <agl@chromium.org> |
| 3 Date: Thu, 25 Jul 2013 14:57:38 -0400 |
| 4 Subject: [PATCH 39/50] tls1_change_cipher_state_rewrite |
| 5 |
| 6 The previous version of the function made adding AEAD changes very |
| 7 difficult. This change should be a semantic no-op - it should be purely |
| 8 a cleanup. |
| 9 --- |
| 10 ssl/ssl.h | 1 + |
| 11 ssl/ssl_err.c | 2 +- |
| 12 ssl/t1_enc.c | 445 +++++++++++++++++++++++++++++++--------------------------- |
| 13 3 files changed, 240 insertions(+), 208 deletions(-) |
| 14 |
| 15 diff --git a/ssl/ssl.h b/ssl/ssl.h |
| 16 index 68e5648..672f3eb 100644 |
| 17 --- a/ssl/ssl.h |
| 18 +++ b/ssl/ssl.h |
| 19 @@ -2439,6 +2439,7 @@ void ERR_load_SSL_strings(void); |
| 20 #define SSL_F_SSL_WRITE 208 |
| 21 #define SSL_F_TLS1_CERT_VERIFY_MAC 286 |
| 22 #define SSL_F_TLS1_CHANGE_CIPHER_STATE 209 |
| 23 +#define SSL_F_TLS1_CHANGE_CIPHER_STATE_CIPHER 338 |
| 24 #define SSL_F_TLS1_CHECK_SERVERHELLO_TLSEXT 274 |
| 25 #define SSL_F_TLS1_ENC 210 |
| 26 #define SSL_F_TLS1_EXPORT_KEYING_MATERIAL 314 |
| 27 diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c |
| 28 index fc98e6c..97b2a0d 100644 |
| 29 --- a/ssl/ssl_err.c |
| 30 +++ b/ssl/ssl_err.c |
| 31 @@ -280,7 +280,7 @@ static ERR_STRING_DATA SSL_str_functs[]= |
| 32 {ERR_FUNC(SSL_F_SSL_VERIFY_CERT_CHAIN), "SSL_VERIFY_CERT_CHAIN"}, |
| 33 {ERR_FUNC(SSL_F_SSL_WRITE), "SSL_write"}, |
| 34 {ERR_FUNC(SSL_F_TLS1_CERT_VERIFY_MAC), "tls1_cert_verify_mac"}, |
| 35 -{ERR_FUNC(SSL_F_TLS1_CHANGE_CIPHER_STATE), "TLS1_CHANGE_CIPHER_STATE"}, |
| 36 +{ERR_FUNC(SSL_F_TLS1_CHANGE_CIPHER_STATE_CIPHER), "TLS1_CHANGE_CIPHER_STAT
E_CIPHER"}, |
| 37 {ERR_FUNC(SSL_F_TLS1_CHECK_SERVERHELLO_TLSEXT), "TLS1_CHECK_SERVERHELLO_
TLSEXT"}, |
| 38 {ERR_FUNC(SSL_F_TLS1_ENC), "TLS1_ENC"}, |
| 39 {ERR_FUNC(SSL_F_TLS1_EXPORT_KEYING_MATERIAL), "TLS1_EXPORT_KEYING_MATERIAL"}, |
| 40 diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c |
| 41 index 3649544..e1f91ba 100644 |
| 42 --- a/ssl/t1_enc.c |
| 43 +++ b/ssl/t1_enc.c |
| 44 @@ -316,56 +316,30 @@ static int tls1_generate_key_block(SSL *s, unsigned char *
km, |
| 45 return ret; |
| 46 } |
| 47 |
| 48 -int tls1_change_cipher_state(SSL *s, int which) |
| 49 +/* tls1_change_cipher_state_cipher performs the work needed to switch cipher |
| 50 + * states when using EVP_CIPHER. The argument |is_read| is true iff this |
| 51 + * function is being called due to reading, as opposed to writing, a |
| 52 + * ChangeCipherSpec message. In order to support export ciphersuites, |
| 53 + * use_client_keys indicates whether the key material provided is in the |
| 54 + * "client write" direction. */ |
| 55 +static int tls1_change_cipher_state_cipher( |
| 56 + SSL *s, char is_read, char use_client_keys, |
| 57 + const unsigned char *mac_secret, unsigned mac_secret_len, |
| 58 + const unsigned char *key, unsigned key_len, |
| 59 + const unsigned char *iv, unsigned iv_len) |
| 60 { |
| 61 - static const unsigned char empty[]=""; |
| 62 - unsigned char *p,*mac_secret; |
| 63 - unsigned char *exp_label; |
| 64 - unsigned char tmp1[EVP_MAX_KEY_LENGTH]; |
| 65 - unsigned char tmp2[EVP_MAX_KEY_LENGTH]; |
| 66 - unsigned char iv1[EVP_MAX_IV_LENGTH*2]; |
| 67 - unsigned char iv2[EVP_MAX_IV_LENGTH*2]; |
| 68 - unsigned char *ms,*key,*iv; |
| 69 - int client_write; |
| 70 - EVP_CIPHER_CTX *dd; |
| 71 - const EVP_CIPHER *c; |
| 72 -#ifndef OPENSSL_NO_COMP |
| 73 - const SSL_COMP *comp; |
| 74 -#endif |
| 75 - const EVP_MD *m; |
| 76 - int mac_type; |
| 77 - int *mac_secret_size; |
| 78 + const EVP_CIPHER *cipher = s->s3->tmp.new_sym_enc; |
| 79 + const char is_export = SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) != 0; |
| 80 + EVP_CIPHER_CTX *cipher_ctx; |
| 81 EVP_MD_CTX *mac_ctx; |
| 82 - EVP_PKEY *mac_key; |
| 83 - int is_export,n,i,j,k,exp_label_len,cl; |
| 84 - int reuse_dd = 0; |
| 85 + char is_aead_cipher; |
| 86 |
| 87 - is_export=SSL_C_IS_EXPORT(s->s3->tmp.new_cipher); |
| 88 - c=s->s3->tmp.new_sym_enc; |
| 89 - m=s->s3->tmp.new_hash; |
| 90 - mac_type = s->s3->tmp.new_mac_pkey_type; |
| 91 -#ifndef OPENSSL_NO_COMP |
| 92 - comp=s->s3->tmp.new_compression; |
| 93 -#endif |
| 94 + unsigned char export_tmp1[EVP_MAX_KEY_LENGTH]; |
| 95 + unsigned char export_tmp2[EVP_MAX_KEY_LENGTH]; |
| 96 + unsigned char export_iv1[EVP_MAX_IV_LENGTH * 2]; |
| 97 + unsigned char export_iv2[EVP_MAX_IV_LENGTH * 2]; |
| 98 |
| 99 -#ifdef KSSL_DEBUG |
| 100 - printf("tls1_change_cipher_state(which= %d) w/\n", which); |
| 101 - printf("\talg= %ld/%ld, comp= %p\n", |
| 102 - s->s3->tmp.new_cipher->algorithm_mkey, |
| 103 - s->s3->tmp.new_cipher->algorithm_auth, |
| 104 - comp); |
| 105 - printf("\tevp_cipher == %p ==? &d_cbc_ede_cipher3\n", c); |
| 106 - printf("\tevp_cipher: nid, blksz= %d, %d, keylen=%d, ivlen=%d\n", |
| 107 - c->nid,c->block_size,c->key_len,c->iv_len); |
| 108 - printf("\tkey_block: len= %d, data= ", s->s3->tmp.key_block_length); |
| 109 - { |
| 110 - int i; |
| 111 - for (i=0; i<s->s3->tmp.key_block_length; i++) |
| 112 - printf("%02x", s->s3->tmp.key_block[i]); printf("\n"); |
| 113 - } |
| 114 -#endif /* KSSL_DEBUG */ |
| 115 - |
| 116 - if (which & SSL3_CC_READ) |
| 117 + if (is_read) |
| 118 { |
| 119 if (s->s3->tmp.new_cipher->algorithm2 & TLS1_STREAM_MAC) |
| 120 s->mac_flags |= SSL_MAC_FLAG_READ_MAC_STREAM; |
| 121 @@ -373,206 +347,257 @@ int tls1_change_cipher_state(SSL *s, int which) |
| 122 s->mac_flags &= ~SSL_MAC_FLAG_READ_MAC_STREAM; |
| 123 |
| 124 if (s->enc_read_ctx != NULL) |
| 125 - reuse_dd = 1; |
| 126 + EVP_CIPHER_CTX_cleanup(s->enc_read_ctx); |
| 127 else if ((s->enc_read_ctx=OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))
) == NULL) |
| 128 goto err; |
| 129 else |
| 130 /* make sure it's intialized in case we exit later with
an error */ |
| 131 EVP_CIPHER_CTX_init(s->enc_read_ctx); |
| 132 - dd= s->enc_read_ctx; |
| 133 - mac_ctx=ssl_replace_hash(&s->read_hash,NULL); |
| 134 -#ifndef OPENSSL_NO_COMP |
| 135 - if (s->expand != NULL) |
| 136 - { |
| 137 - COMP_CTX_free(s->expand); |
| 138 - s->expand=NULL; |
| 139 - } |
| 140 - if (comp != NULL) |
| 141 - { |
| 142 - s->expand=COMP_CTX_new(comp->method); |
| 143 - if (s->expand == NULL) |
| 144 - { |
| 145 - SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,SSL_R_COMP
RESSION_LIBRARY_ERROR); |
| 146 - goto err2; |
| 147 - } |
| 148 - if (s->s3->rrec.comp == NULL) |
| 149 - s->s3->rrec.comp=(unsigned char *) |
| 150 - OPENSSL_malloc(SSL3_RT_MAX_ENCRYPTED_LEN
GTH); |
| 151 - if (s->s3->rrec.comp == NULL) |
| 152 - goto err; |
| 153 - } |
| 154 -#endif |
| 155 - /* this is done by dtls1_reset_seq_numbers for DTLS1_VERSION */ |
| 156 - if (s->version != DTLS1_VERSION) |
| 157 - memset(&(s->s3->read_sequence[0]),0,8); |
| 158 - mac_secret= &(s->s3->read_mac_secret[0]); |
| 159 - mac_secret_size=&(s->s3->read_mac_secret_size); |
| 160 + |
| 161 + cipher_ctx = s->enc_read_ctx; |
| 162 + mac_ctx = ssl_replace_hash(&s->read_hash, NULL); |
| 163 + |
| 164 + memcpy(s->s3->read_mac_secret, mac_secret, mac_secret_len); |
| 165 + s->s3->read_mac_secret_size = mac_secret_len; |
| 166 } |
| 167 else |
| 168 { |
| 169 if (s->s3->tmp.new_cipher->algorithm2 & TLS1_STREAM_MAC) |
| 170 s->mac_flags |= SSL_MAC_FLAG_WRITE_MAC_STREAM; |
| 171 - else |
| 172 + else |
| 173 s->mac_flags &= ~SSL_MAC_FLAG_WRITE_MAC_STREAM; |
| 174 + |
| 175 if (s->enc_write_ctx != NULL) |
| 176 - reuse_dd = 1; |
| 177 + EVP_CIPHER_CTX_cleanup(s->enc_write_ctx); |
| 178 else if ((s->enc_write_ctx=OPENSSL_malloc(sizeof(EVP_CIPHER_CTX)
)) == NULL) |
| 179 goto err; |
| 180 else |
| 181 /* make sure it's intialized in case we exit later with
an error */ |
| 182 EVP_CIPHER_CTX_init(s->enc_write_ctx); |
| 183 - dd= s->enc_write_ctx; |
| 184 - mac_ctx = ssl_replace_hash(&s->write_hash,NULL); |
| 185 -#ifndef OPENSSL_NO_COMP |
| 186 - if (s->compress != NULL) |
| 187 - { |
| 188 - COMP_CTX_free(s->compress); |
| 189 - s->compress=NULL; |
| 190 - } |
| 191 - if (comp != NULL) |
| 192 - { |
| 193 - s->compress=COMP_CTX_new(comp->method); |
| 194 - if (s->compress == NULL) |
| 195 - { |
| 196 - SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,SSL_R_COMP
RESSION_LIBRARY_ERROR); |
| 197 - goto err2; |
| 198 - } |
| 199 - } |
| 200 -#endif |
| 201 - /* this is done by dtls1_reset_seq_numbers for DTLS1_VERSION */ |
| 202 - if (s->version != DTLS1_VERSION) |
| 203 - memset(&(s->s3->write_sequence[0]),0,8); |
| 204 - mac_secret= &(s->s3->write_mac_secret[0]); |
| 205 - mac_secret_size = &(s->s3->write_mac_secret_size); |
| 206 - } |
| 207 - |
| 208 - if (reuse_dd) |
| 209 - EVP_CIPHER_CTX_cleanup(dd); |
| 210 |
| 211 - p=s->s3->tmp.key_block; |
| 212 - i=*mac_secret_size=s->s3->tmp.new_mac_secret_size; |
| 213 + cipher_ctx = s->enc_write_ctx; |
| 214 + mac_ctx = ssl_replace_hash(&s->write_hash, NULL); |
| 215 |
| 216 - cl=EVP_CIPHER_key_length(c); |
| 217 - j=is_export ? (cl < SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher) ? |
| 218 - cl : SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher)) : cl; |
| 219 - /* Was j=(exp)?5:EVP_CIPHER_key_length(c); */ |
| 220 - /* If GCM mode only part of IV comes from PRF */ |
| 221 - if (EVP_CIPHER_mode(c) == EVP_CIPH_GCM_MODE) |
| 222 - k = EVP_GCM_TLS_FIXED_IV_LEN; |
| 223 - else |
| 224 - k=EVP_CIPHER_iv_length(c); |
| 225 - if ( (which == SSL3_CHANGE_CIPHER_CLIENT_WRITE) || |
| 226 - (which == SSL3_CHANGE_CIPHER_SERVER_READ)) |
| 227 - { |
| 228 - ms= &(p[ 0]); n=i+i; |
| 229 - key= &(p[ n]); n+=j+j; |
| 230 - iv= &(p[ n]); n+=k+k; |
| 231 - exp_label=(unsigned char *)TLS_MD_CLIENT_WRITE_KEY_CONST; |
| 232 - exp_label_len=TLS_MD_CLIENT_WRITE_KEY_CONST_SIZE; |
| 233 - client_write=1; |
| 234 - } |
| 235 - else |
| 236 - { |
| 237 - n=i; |
| 238 - ms= &(p[ n]); n+=i+j; |
| 239 - key= &(p[ n]); n+=j+k; |
| 240 - iv= &(p[ n]); n+=k; |
| 241 - exp_label=(unsigned char *)TLS_MD_SERVER_WRITE_KEY_CONST; |
| 242 - exp_label_len=TLS_MD_SERVER_WRITE_KEY_CONST_SIZE; |
| 243 - client_write=0; |
| 244 + memcpy(s->s3->write_mac_secret, mac_secret, mac_secret_len); |
| 245 + s->s3->write_mac_secret_size = mac_secret_len; |
| 246 } |
| 247 |
| 248 - if (n > s->s3->tmp.key_block_length) |
| 249 - { |
| 250 - SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,ERR_R_INTERNAL_ERROR); |
| 251 - goto err2; |
| 252 - } |
| 253 - |
| 254 - memcpy(mac_secret,ms,i); |
| 255 - |
| 256 - if (!(EVP_CIPHER_flags(c)&EVP_CIPH_FLAG_AEAD_CIPHER)) |
| 257 - { |
| 258 - mac_key = EVP_PKEY_new_mac_key(mac_type, NULL, |
| 259 - mac_secret,*mac_secret_size); |
| 260 - EVP_DigestSignInit(mac_ctx,NULL,m,NULL,mac_key); |
| 261 - EVP_PKEY_free(mac_key); |
| 262 - } |
| 263 -#ifdef TLS_DEBUG |
| 264 -printf("which = %04X\nmac key=",which); |
| 265 -{ int z; for (z=0; z<i; z++) printf("%02X%c",ms[z],((z+1)%16)?' ':'\n'); } |
| 266 -#endif |
| 267 if (is_export) |
| 268 { |
| 269 /* In here I set both the read and write key/iv to the |
| 270 * same value since only the correct one will be used :-). |
| 271 */ |
| 272 + const unsigned char *label; |
| 273 + unsigned label_len; |
| 274 + |
| 275 + if (use_client_keys) |
| 276 + { |
| 277 + label = (const unsigned char*) TLS_MD_CLIENT_WRITE_KEY_C
ONST; |
| 278 + label_len = TLS_MD_CLIENT_WRITE_KEY_CONST_SIZE; |
| 279 + } |
| 280 + else |
| 281 + { |
| 282 + label = (const unsigned char*) TLS_MD_SERVER_WRITE_KEY_C
ONST; |
| 283 + label_len = TLS_MD_SERVER_WRITE_KEY_CONST_SIZE; |
| 284 + } |
| 285 + |
| 286 if (!tls1_PRF(ssl_get_algorithm2(s), |
| 287 - exp_label,exp_label_len, |
| 288 - s->s3->client_random,SSL3_RANDOM_SIZE, |
| 289 - s->s3->server_random,SSL3_RANDOM_SIZE, |
| 290 - NULL,0,NULL,0, |
| 291 - key,j,tmp1,tmp2,EVP_CIPHER_key_length(c))) |
| 292 - goto err2; |
| 293 - key=tmp1; |
| 294 + label, label_len, |
| 295 + s->s3->client_random, SSL3_RANDOM_SIZE, |
| 296 + s->s3->server_random, SSL3_RANDOM_SIZE, |
| 297 + NULL, 0, NULL, 0, |
| 298 + key /* secret */, key_len /* secret length */, |
| 299 + export_tmp1 /* output */, |
| 300 + export_tmp2 /* scratch space */, |
| 301 + EVP_CIPHER_key_length(s->s3->tmp.new_sym_enc) /*
output length */)) |
| 302 + return 0; |
| 303 + key = export_tmp1; |
| 304 |
| 305 - if (k > 0) |
| 306 + if (iv_len > 0) |
| 307 { |
| 308 + static const unsigned char empty[] = ""; |
| 309 + |
| 310 if (!tls1_PRF(ssl_get_algorithm2(s), |
| 311 - TLS_MD_IV_BLOCK_CONST,TLS_MD_IV_BLOCK_CO
NST_SIZE, |
| 312 - s->s3->client_random,SSL3_RANDOM_SIZE, |
| 313 - s->s3->server_random,SSL3_RANDOM_SIZE, |
| 314 - NULL,0,NULL,0, |
| 315 - empty,0,iv1,iv2,k*2)) |
| 316 - goto err2; |
| 317 - if (client_write) |
| 318 - iv=iv1; |
| 319 + TLS_MD_IV_BLOCK_CONST, TLS_MD_IV_BLOCK_C
ONST_SIZE, |
| 320 + s->s3->client_random, SSL3_RANDOM_SIZE, |
| 321 + s->s3->server_random, SSL3_RANDOM_SIZE, |
| 322 + NULL, 0, NULL, 0, |
| 323 + empty /* secret */ ,0 /* secret length *
/, |
| 324 + export_iv1 /* output */, |
| 325 + export_iv2 /* scratch space */, |
| 326 + iv_len * 2 /* output length */)) |
| 327 + return 0; |
| 328 + |
| 329 + if (use_client_keys) |
| 330 + iv = export_iv1; |
| 331 else |
| 332 - iv= &(iv1[k]); |
| 333 + iv = &export_iv1[iv_len]; |
| 334 } |
| 335 } |
| 336 |
| 337 - s->session->key_arg_length=0; |
| 338 -#ifdef KSSL_DEBUG |
| 339 - { |
| 340 - int i; |
| 341 - printf("EVP_CipherInit_ex(dd,c,key=,iv=,which)\n"); |
| 342 - printf("\tkey= "); for (i=0; i<c->key_len; i++) printf("%02x", key[i]); |
| 343 - printf("\n"); |
| 344 - printf("\t iv= "); for (i=0; i<c->iv_len; i++) printf("%02x", iv[i]); |
| 345 - printf("\n"); |
| 346 - } |
| 347 -#endif /* KSSL_DEBUG */ |
| 348 + /* is_aead_cipher indicates whether the EVP_CIPHER implements an AEAD |
| 349 + * interface. This is different from the newer EVP_AEAD interface. */ |
| 350 + is_aead_cipher = (EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER)
!= 0; |
| 351 |
| 352 - if (EVP_CIPHER_mode(c) == EVP_CIPH_GCM_MODE) |
| 353 + if (!is_aead_cipher) |
| 354 { |
| 355 - EVP_CipherInit_ex(dd,c,NULL,key,NULL,(which & SSL3_CC_WRITE)); |
| 356 - EVP_CIPHER_CTX_ctrl(dd, EVP_CTRL_GCM_SET_IV_FIXED, k, iv); |
| 357 + EVP_PKEY *mac_key = |
| 358 + EVP_PKEY_new_mac_key(s->s3->tmp.new_mac_pkey_type, |
| 359 + NULL, mac_secret, mac_secret_len); |
| 360 + if (!mac_key) |
| 361 + return 0; |
| 362 + EVP_DigestSignInit(mac_ctx, NULL, s->s3->tmp.new_hash, NULL, mac
_key); |
| 363 + EVP_PKEY_free(mac_key); |
| 364 } |
| 365 - else |
| 366 - EVP_CipherInit_ex(dd,c,NULL,key,iv,(which & SSL3_CC_WRITE)); |
| 367 + |
| 368 + if (EVP_CIPHER_mode(cipher) == EVP_CIPH_GCM_MODE) |
| 369 + { |
| 370 + EVP_CipherInit_ex(cipher_ctx, cipher, NULL /* engine */, key, |
| 371 + NULL /* iv */, !is_read); |
| 372 + EVP_CIPHER_CTX_ctrl(cipher_ctx, EVP_CTRL_GCM_SET_IV_FIXED, iv_le
n, (void*) iv); |
| 373 + } |
| 374 + else |
| 375 + EVP_CipherInit_ex(cipher_ctx, cipher, NULL /* engine */, key, iv
, !is_read); |
| 376 |
| 377 /* Needed for "composite" AEADs, such as RC4-HMAC-MD5 */ |
| 378 - if ((EVP_CIPHER_flags(c)&EVP_CIPH_FLAG_AEAD_CIPHER) && *mac_secret_size) |
| 379 - EVP_CIPHER_CTX_ctrl(dd,EVP_CTRL_AEAD_SET_MAC_KEY, |
| 380 - *mac_secret_size,mac_secret); |
| 381 - |
| 382 -#ifdef TLS_DEBUG |
| 383 -printf("which = %04X\nkey=",which); |
| 384 -{ int z; for (z=0; z<EVP_CIPHER_key_length(c); z++) printf("%02X%c",key[z],((z+
1)%16)?' ':'\n'); } |
| 385 -printf("\niv="); |
| 386 -{ int z; for (z=0; z<k; z++) printf("%02X%c",iv[z],((z+1)%16)?' ':'\n'); } |
| 387 -printf("\n"); |
| 388 -#endif |
| 389 - |
| 390 - OPENSSL_cleanse(tmp1,sizeof(tmp1)); |
| 391 - OPENSSL_cleanse(tmp2,sizeof(tmp1)); |
| 392 - OPENSSL_cleanse(iv1,sizeof(iv1)); |
| 393 - OPENSSL_cleanse(iv2,sizeof(iv2)); |
| 394 - return(1); |
| 395 + if (is_aead_cipher && mac_secret_len > 0) |
| 396 + EVP_CIPHER_CTX_ctrl(cipher_ctx, EVP_CTRL_AEAD_SET_MAC_KEY, |
| 397 + mac_secret_len, (void*) mac_secret); |
| 398 + |
| 399 + if (is_export) |
| 400 + { |
| 401 + OPENSSL_cleanse(export_tmp1, sizeof(export_tmp1)); |
| 402 + OPENSSL_cleanse(export_tmp2, sizeof(export_tmp1)); |
| 403 + OPENSSL_cleanse(export_iv1, sizeof(export_iv1)); |
| 404 + OPENSSL_cleanse(export_iv2, sizeof(export_iv2)); |
| 405 + } |
| 406 + |
| 407 + return 1; |
| 408 + |
| 409 +err: |
| 410 + SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE_CIPHER, ERR_R_MALLOC_FAILURE); |
| 411 + return 0; |
| 412 + } |
| 413 + |
| 414 +int tls1_change_cipher_state(SSL *s, int which) |
| 415 + { |
| 416 + /* is_read is true if we have just read a ChangeCipherSpec message - |
| 417 + * i.e. we need to update the read cipherspec. Otherwise we have just |
| 418 + * written one. */ |
| 419 + const char is_read = (which & SSL3_CC_READ) != 0; |
| 420 + /* use_client_keys is true if we wish to use the keys for the "client |
| 421 + * write" direction. This is the case if we're a client sending a |
| 422 + * ChangeCipherSpec, or a server reading a client's ChangeCipherSpec. */ |
| 423 + const char use_client_keys = which == SSL3_CHANGE_CIPHER_CLIENT_WRITE || |
| 424 + which == SSL3_CHANGE_CIPHER_SERVER_READ; |
| 425 + const unsigned char *client_write_mac_secret, *server_write_mac_secret,
*mac_secret; |
| 426 + const unsigned char *client_write_key, *server_write_key, *key; |
| 427 + const unsigned char *client_write_iv, *server_write_iv, *iv; |
| 428 + const EVP_CIPHER *cipher = s->s3->tmp.new_sym_enc; |
| 429 + unsigned key_len, iv_len, mac_secret_len; |
| 430 + const unsigned char *key_data; |
| 431 + const char is_export = SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) != 0; |
| 432 + |
| 433 + /* Update compression contexts. */ |
| 434 +#ifndef OPENSSL_NO_COMP |
| 435 + const SSL_COMP *comp = s->s3->tmp.new_compression; |
| 436 + |
| 437 + if (is_read) |
| 438 + { |
| 439 + if (s->expand != NULL) |
| 440 + { |
| 441 + COMP_CTX_free(s->expand); |
| 442 + s->expand = NULL; |
| 443 + } |
| 444 + if (comp != NULL) |
| 445 + { |
| 446 + s->expand=COMP_CTX_new(comp->method); |
| 447 + if (s->expand == NULL) |
| 448 + { |
| 449 + SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,SSL_R_COMP
RESSION_LIBRARY_ERROR); |
| 450 + return 0; |
| 451 + } |
| 452 + if (s->s3->rrec.comp == NULL) |
| 453 + s->s3->rrec.comp = |
| 454 + (unsigned char *)OPENSSL_malloc(SSL3_RT_
MAX_ENCRYPTED_LENGTH); |
| 455 + if (s->s3->rrec.comp == NULL) |
| 456 + goto err; |
| 457 + } |
| 458 + } |
| 459 + else |
| 460 + { |
| 461 + if (s->compress != NULL) |
| 462 + { |
| 463 + COMP_CTX_free(s->compress); |
| 464 + s->compress = NULL; |
| 465 + } |
| 466 + if (comp != NULL) |
| 467 + { |
| 468 + s->compress = COMP_CTX_new(comp->method); |
| 469 + if (s->compress == NULL) |
| 470 + { |
| 471 + SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,SSL_R_COMP
RESSION_LIBRARY_ERROR); |
| 472 + return 0; |
| 473 + } |
| 474 + } |
| 475 + } |
| 476 +#endif /* OPENSSL_NO_COMP */ |
| 477 + |
| 478 + /* Reset sequence number to zero. */ |
| 479 + memset(is_read ? s->s3->read_sequence : s->s3->write_sequence, 0, 8); |
| 480 + |
| 481 + /* key_arg is used for SSLv2. We don't need it for TLS. */ |
| 482 + s->session->key_arg_length = 0; |
| 483 + |
| 484 + mac_secret_len = s->s3->tmp.new_mac_secret_size; |
| 485 + |
| 486 + key_len = EVP_CIPHER_key_length(cipher); |
| 487 + if (is_export && key_len > SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher)
) |
| 488 + key_len = SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher); |
| 489 + |
| 490 + if (EVP_CIPHER_mode(cipher) == EVP_CIPH_GCM_MODE) |
| 491 + iv_len = EVP_GCM_TLS_FIXED_IV_LEN; |
| 492 + else |
| 493 + iv_len = EVP_CIPHER_iv_length(cipher); |
| 494 + |
| 495 + key_data = s->s3->tmp.key_block; |
| 496 + client_write_mac_secret = key_data; key_data += mac_secret_len; |
| 497 + server_write_mac_secret = key_data; key_data += mac_secret_len; |
| 498 + client_write_key = key_data; key_data += key_len; |
| 499 + server_write_key = key_data; key_data += key_len; |
| 500 + client_write_iv = key_data; key_data += iv_len; |
| 501 + server_write_iv = key_data; key_data += iv_len; |
| 502 + |
| 503 + if (use_client_keys) |
| 504 + { |
| 505 + mac_secret = client_write_mac_secret; |
| 506 + key = client_write_key; |
| 507 + iv = client_write_iv; |
| 508 + } |
| 509 + else |
| 510 + { |
| 511 + mac_secret = server_write_mac_secret; |
| 512 + key = server_write_key; |
| 513 + iv = server_write_iv; |
| 514 + } |
| 515 + |
| 516 + if (key_data - s->s3->tmp.key_block != s->s3->tmp.key_block_length) |
| 517 + { |
| 518 + SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,ERR_R_INTERNAL_ERROR); |
| 519 + return 0; |
| 520 + } |
| 521 + |
| 522 + if (!tls1_change_cipher_state_cipher(s, is_read, use_client_keys, |
| 523 + mac_secret, mac_secret_len, |
| 524 + key, key_len, |
| 525 + iv, iv_len)) { |
| 526 + return 0; |
| 527 + } |
| 528 + |
| 529 + return 1; |
| 530 err: |
| 531 - SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,ERR_R_MALLOC_FAILURE); |
| 532 -err2: |
| 533 - return(0); |
| 534 + SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE); |
| 535 + return 0; |
| 536 } |
| 537 |
| 538 int tls1_setup_key_block(SSL *s) |
| 539 @@ -584,6 +609,7 @@ int tls1_setup_key_block(SSL *s) |
| 540 SSL_COMP *comp; |
| 541 int mac_type= NID_undef,mac_secret_size=0; |
| 542 int ret=0; |
| 543 + int iv_len; |
| 544 |
| 545 #ifdef KSSL_DEBUG |
| 546 printf ("tls1_setup_key_block()\n"); |
| 547 @@ -598,11 +624,16 @@ int tls1_setup_key_block(SSL *s) |
| 548 return(0); |
| 549 } |
| 550 |
| 551 + if (EVP_CIPHER_mode(c) == EVP_CIPH_GCM_MODE) |
| 552 + iv_len = EVP_GCM_TLS_FIXED_IV_LEN; |
| 553 + else |
| 554 + iv_len = EVP_CIPHER_iv_length(c); |
| 555 + |
| 556 s->s3->tmp.new_sym_enc=c; |
| 557 s->s3->tmp.new_hash=hash; |
| 558 s->s3->tmp.new_mac_pkey_type = mac_type; |
| 559 s->s3->tmp.new_mac_secret_size = mac_secret_size; |
| 560 - num=EVP_CIPHER_key_length(c)+mac_secret_size+EVP_CIPHER_iv_length(c); |
| 561 + num=EVP_CIPHER_key_length(c)+mac_secret_size+iv_len; |
| 562 num*=2; |
| 563 |
| 564 ssl3_cleanup_key_block(s); |
| 565 -- |
| 566 1.8.4.1 |
| 567 |
OLD | NEW |