int SSL_export_keying_material(SSL *ssl, uint8_t *out, size_t out_len, const char *label, size_t label_len, const uint8_t *context, size_t context_len, int use_context) { if (!ssl->s3->have_version || ssl->version == SSL3_VERSION) { return 0; } /* Exporters may not be used in the middle of a renegotiation. */ if (SSL_in_init(ssl) && !SSL_in_false_start(ssl)) { return 0; } if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) { return tls13_export_keying_material(ssl, out, out_len, label, label_len, context, context_len, use_context); } size_t seed_len = 2 * SSL3_RANDOM_SIZE; if (use_context) { if (context_len >= 1u << 16) { OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW); return 0; } seed_len += 2 + context_len; } uint8_t *seed = OPENSSL_malloc(seed_len); if (seed == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); return 0; } OPENSSL_memcpy(seed, ssl->s3->client_random, SSL3_RANDOM_SIZE); OPENSSL_memcpy(seed + SSL3_RANDOM_SIZE, ssl->s3->server_random, SSL3_RANDOM_SIZE); if (use_context) { seed[2 * SSL3_RANDOM_SIZE] = (uint8_t)(context_len >> 8); seed[2 * SSL3_RANDOM_SIZE + 1] = (uint8_t)context_len; OPENSSL_memcpy(seed + 2 * SSL3_RANDOM_SIZE + 2, context, context_len); } const EVP_MD *digest = ssl_get_handshake_digest( SSL_get_session(ssl)->cipher->algorithm_prf, ssl3_protocol_version(ssl)); if (digest == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); return 0; } int ret = tls1_prf(digest, out, out_len, SSL_get_session(ssl)->master_key, SSL_get_session(ssl)->master_key_length, label, label_len, seed, seed_len, NULL, 0); OPENSSL_free(seed); return ret; }
int tls1_generate_master_secret(SSL_HANDSHAKE *hs, uint8_t *out, const uint8_t *premaster, size_t premaster_len) { const SSL *ssl = hs->ssl; if (hs->extended_master_secret) { uint8_t digests[EVP_MAX_MD_SIZE]; size_t digests_len; if (!SSL_TRANSCRIPT_get_hash(&hs->transcript, digests, &digests_len) || !tls1_prf(SSL_TRANSCRIPT_md(&hs->transcript), out, SSL3_MASTER_SECRET_SIZE, premaster, premaster_len, TLS_MD_EXTENDED_MASTER_SECRET_CONST, TLS_MD_EXTENDED_MASTER_SECRET_CONST_SIZE, digests, digests_len, NULL, 0)) { return 0; } } else { if (ssl3_protocol_version(ssl) == SSL3_VERSION) { if (!ssl3_prf(out, SSL3_MASTER_SECRET_SIZE, premaster, premaster_len, TLS_MD_MASTER_SECRET_CONST, TLS_MD_MASTER_SECRET_CONST_SIZE, ssl->s3->client_random, SSL3_RANDOM_SIZE, ssl->s3->server_random, SSL3_RANDOM_SIZE)) { return 0; } } else { if (!tls1_prf(SSL_TRANSCRIPT_md(&hs->transcript), out, SSL3_MASTER_SECRET_SIZE, premaster, premaster_len, TLS_MD_MASTER_SECRET_CONST, TLS_MD_MASTER_SECRET_CONST_SIZE, ssl->s3->client_random, SSL3_RANDOM_SIZE, ssl->s3->server_random, SSL3_RANDOM_SIZE)) { return 0; } } } return SSL3_MASTER_SECRET_SIZE; }
int SSL_generate_key_block(const SSL *ssl, uint8_t *out, size_t out_len) { if (ssl3_protocol_version(ssl) == SSL3_VERSION) { return ssl3_prf(out, out_len, SSL_get_session(ssl)->master_key, SSL_get_session(ssl)->master_key_length, TLS_MD_KEY_EXPANSION_CONST, TLS_MD_KEY_EXPANSION_CONST_SIZE, ssl->s3->server_random, SSL3_RANDOM_SIZE, ssl->s3->client_random, SSL3_RANDOM_SIZE); } const EVP_MD *digest = ssl_get_handshake_digest( SSL_get_session(ssl)->cipher->algorithm_prf, ssl3_protocol_version(ssl)); if (digest == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); return 0; } return tls1_prf(digest, out, out_len, SSL_get_session(ssl)->master_key, SSL_get_session(ssl)->master_key_length, TLS_MD_KEY_EXPANSION_CONST, TLS_MD_KEY_EXPANSION_CONST_SIZE, ssl->s3->server_random, SSL3_RANDOM_SIZE, ssl->s3->client_random, SSL3_RANDOM_SIZE); }
int ssl_derive_keys(ssl_context * ssl) { size_t i; md5_context md5; sha1_context sha1; uint8_t tmp[64]; uint8_t padding[16]; uint8_t sha1sum[20]; uint8_t keyblk[256]; uint8_t *key1; uint8_t *key2; SSL_DEBUG_MSG(2, ("=> derive keys")); /* * SSLv3: * master = * MD5( premaster + SHA1( 'A' + premaster + randbytes ) ) + * MD5( premaster + SHA1( 'BB' + premaster + randbytes ) ) + * MD5( premaster + SHA1( 'CCC' + premaster + randbytes ) ) * * TLSv1: * master = PRF( premaster, "master secret", randbytes )[0..47] */ if (ssl->resume == 0) { size_t len = ssl->pmslen; SSL_DEBUG_BUF(3, "premaster secret", ssl->premaster, len); if (ssl->minor_ver == SSL_MINOR_VERSION_0) { for (i = 0; i < 3; i++) { memset(padding, 'A' + i, 1 + i); sha1_starts(&sha1); sha1_update(&sha1, padding, 1 + i); sha1_update(&sha1, ssl->premaster, len); sha1_update(&sha1, ssl->randbytes, 64); sha1_finish(&sha1, sha1sum); md5_starts(&md5); md5_update(&md5, ssl->premaster, len); md5_update(&md5, sha1sum, 20); md5_finish(&md5, ssl->session->master + i * 16); } } else tls1_prf(ssl->premaster, len, "master secret", ssl->randbytes, 64, ssl->session->master, 48); memset(ssl->premaster, 0, sizeof(ssl->premaster)); } else SSL_DEBUG_MSG(3, ("no premaster (session resumed)")); /* * Swap the client and server random values. */ memcpy(tmp, ssl->randbytes, 64); memcpy(ssl->randbytes, tmp + 32, 32); memcpy(ssl->randbytes + 32, tmp, 32); memset(tmp, 0, sizeof(tmp)); /* * SSLv3: * key block = * MD5( master + SHA1( 'A' + master + randbytes ) ) + * MD5( master + SHA1( 'BB' + master + randbytes ) ) + * MD5( master + SHA1( 'CCC' + master + randbytes ) ) + * MD5( master + SHA1( 'DDDD' + master + randbytes ) ) + * ... * * TLSv1: * key block = PRF( master, "key expansion", randbytes ) */ if (ssl->minor_ver == SSL_MINOR_VERSION_0) { for (i = 0; i < 16; i++) { memset(padding, 'A' + i, 1 + i); sha1_starts(&sha1); sha1_update(&sha1, padding, 1 + i); sha1_update(&sha1, ssl->session->master, 48); sha1_update(&sha1, ssl->randbytes, 64); sha1_finish(&sha1, sha1sum); md5_starts(&md5); md5_update(&md5, ssl->session->master, 48); md5_update(&md5, sha1sum, 20); md5_finish(&md5, keyblk + i * 16); } memset(&md5, 0, sizeof(md5)); memset(&sha1, 0, sizeof(sha1)); memset(padding, 0, sizeof(padding)); memset(sha1sum, 0, sizeof(sha1sum)); } else tls1_prf(ssl->session->master, 48, "key expansion", ssl->randbytes, 64, keyblk, 256); SSL_DEBUG_MSG(3, ("cipher = %s", ssl_get_cipher(ssl))); SSL_DEBUG_BUF(3, "master secret", ssl->session->master, 48); SSL_DEBUG_BUF(4, "random bytes", ssl->randbytes, 64); SSL_DEBUG_BUF(4, "key block", keyblk, 256); memset(ssl->randbytes, 0, sizeof(ssl->randbytes)); /* * Determine the appropriate key, IV and MAC length. */ switch (ssl->session->cipher) { #if defined(TROPICSSL_ARC4) case TLS_RSA_WITH_RC4_128_MD5: ssl->keylen = 16; ssl->minlen = 16; ssl->ivlen = 0; ssl->maclen = 16; break; case TLS_RSA_WITH_RC4_128_SHA: ssl->keylen = 16; ssl->minlen = 20; ssl->ivlen = 0; ssl->maclen = 20; break; #endif #if defined(TROPICSSL_DES) case TLS_RSA_WITH_3DES_EDE_CBC_SHA: case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA: ssl->keylen = 24; ssl->minlen = 24; ssl->ivlen = 8; ssl->maclen = 20; break; #endif #if defined(TROPICSSL_AES) case TLS_RSA_WITH_AES_128_CBC_SHA: ssl->keylen = 16; ssl->minlen = 32; ssl->ivlen = 16; ssl->maclen = 20; break; case TLS_RSA_WITH_AES_256_CBC_SHA: case TLS_DHE_RSA_WITH_AES_256_CBC_SHA: ssl->keylen = 32; ssl->minlen = 32; ssl->ivlen = 16; ssl->maclen = 20; break; #endif #if defined(TROPICSSL_CAMELLIA) case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA: ssl->keylen = 16; ssl->minlen = 32; ssl->ivlen = 16; ssl->maclen = 20; break; case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA: case TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA: ssl->keylen = 32; ssl->minlen = 32; ssl->ivlen = 16; ssl->maclen = 20; break; #endif default: SSL_DEBUG_MSG(1, ("cipher %s is not available", ssl_get_cipher(ssl))); return (TROPICSSL_ERR_SSL_FEATURE_UNAVAILABLE); } SSL_DEBUG_MSG(3, ("keylen: %d, minlen: %d, ivlen: %d, maclen: %d", ssl->keylen, ssl->minlen, ssl->ivlen, ssl->maclen)); /* * Finally setup the cipher contexts, IVs and MAC secrets. */ if (ssl->endpoint == SSL_IS_CLIENT) { key1 = keyblk + ssl->maclen * 2; key2 = keyblk + ssl->maclen * 2 + ssl->keylen; memcpy(ssl->mac_enc, keyblk, ssl->maclen); memcpy(ssl->mac_dec, keyblk + ssl->maclen, ssl->maclen); memcpy(ssl->iv_enc, key2 + ssl->keylen, ssl->ivlen); memcpy(ssl->iv_dec, key2 + ssl->keylen + ssl->ivlen, ssl->ivlen); } else { key1 = keyblk + ssl->maclen * 2 + ssl->keylen; key2 = keyblk + ssl->maclen * 2; memcpy(ssl->mac_dec, keyblk, ssl->maclen); memcpy(ssl->mac_enc, keyblk + ssl->maclen, ssl->maclen); memcpy(ssl->iv_dec, key1 + ssl->keylen, ssl->ivlen); memcpy(ssl->iv_enc, key1 + ssl->keylen + ssl->ivlen, ssl->ivlen); } switch (ssl->session->cipher) { #if defined(TROPICSSL_ARC4) case TLS_RSA_WITH_RC4_128_MD5: case TLS_RSA_WITH_RC4_128_SHA: arc4_setup((arc4_context *) ssl->ctx_enc, key1, ssl->keylen); arc4_setup((arc4_context *) ssl->ctx_dec, key2, ssl->keylen); break; #endif #if defined(TROPICSSL_DES) case TLS_RSA_WITH_3DES_EDE_CBC_SHA: case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA: des3_set3key_enc((des3_context *) ssl->ctx_enc, key1); des3_set3key_dec((des3_context *) ssl->ctx_dec, key2); break; #endif #if defined(TROPICSSL_AES) case TLS_RSA_WITH_AES_128_CBC_SHA: aes_setkey_enc((aes_context *) ssl->ctx_enc, key1, 128); aes_setkey_dec((aes_context *) ssl->ctx_dec, key2, 128); break; case TLS_RSA_WITH_AES_256_CBC_SHA: case TLS_DHE_RSA_WITH_AES_256_CBC_SHA: aes_setkey_enc((aes_context *) ssl->ctx_enc, key1, 256); aes_setkey_dec((aes_context *) ssl->ctx_dec, key2, 256); break; #endif #if defined(TROPICSSL_CAMELLIA) case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA: camellia_setkey_enc((camellia_context *) ssl->ctx_enc, key1, 128); camellia_setkey_dec((camellia_context *) ssl->ctx_dec, key2, 128); break; case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA: case TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA: camellia_setkey_enc((camellia_context *) ssl->ctx_enc, key1, 256); camellia_setkey_dec((camellia_context *) ssl->ctx_dec, key2, 256); break; #endif default: return (TROPICSSL_ERR_SSL_FEATURE_UNAVAILABLE); } memset(keyblk, 0, sizeof(keyblk)); SSL_DEBUG_MSG(2, ("<= derive keys")); return (0); }