From 5ac03256db0fe4ca7e3ad1117d096c3a76368b76 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Fri, 9 Jan 2015 09:46:07 +0100 Subject: backported CyaSSL/OpenSSL support for internal webserver instead of MatrixSSL --- release/src/router/cyassl/src/keys.c | 751 +++++++++++++++++++++++++++++++++++ 1 file changed, 751 insertions(+) create mode 100644 release/src/router/cyassl/src/keys.c (limited to 'release/src/router/cyassl/src/keys.c') diff --git a/release/src/router/cyassl/src/keys.c b/release/src/router/cyassl/src/keys.c new file mode 100644 index 00000000..3a51f7fb --- /dev/null +++ b/release/src/router/cyassl/src/keys.c @@ -0,0 +1,751 @@ +/* keys.c + * + * Copyright (C) 2006-2011 Sawtooth Consulting Ltd. + * + * This file is part of CyaSSL. + * + * CyaSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * CyaSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + + +#include "cyassl_int.h" +#include "cyassl_error.h" +#ifdef SHOW_SECRETS + #include +#endif + + +#ifndef NO_TLS + int MakeTlsMasterSecret(SSL*); + void TLS_hmac(SSL* ssl, byte* digest, const byte* buffer, word32 sz, + int content, int verify); +#endif + + + +int SetCipherSpecs(SSL* ssl) +{ + /* ECC extensions */ + if (ssl->options.cipherSuite0 == ECC_BYTE) { + + switch (ssl->options.cipherSuite) { + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = triple_des; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.key_size = DES3_KEY_SIZE; + ssl->specs.block_size = DES_BLOCK_SIZE; + ssl->specs.iv_size = DES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA + case TLS_ECDHE_RSA_WITH_RC4_128_SHA : + ssl->specs.bulk_cipher_algorithm = rc4; + ssl->specs.cipher_type = stream; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.key_size = RC4_KEY_SIZE; + ssl->specs.iv_size = 0; + ssl->specs.block_size = 0; + + break; +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = triple_des; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = ecc_dsa_sa_algo; + ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.key_size = DES3_KEY_SIZE; + ssl->specs.block_size = DES_BLOCK_SIZE; + ssl->specs.iv_size = DES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA : + ssl->specs.bulk_cipher_algorithm = rc4; + ssl->specs.cipher_type = stream; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = ecc_dsa_sa_algo; + ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.key_size = RC4_KEY_SIZE; + ssl->specs.iv_size = 0; + ssl->specs.block_size = 0; + + break; +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = ecc_dsa_sa_algo; + ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = ecc_dsa_sa_algo; + ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + break; +#endif + + default: + return UNSUPPORTED_SUITE; + } + } else { /* Normal suites */ + switch (ssl->options.cipherSuite) { + +#ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA + case SSL_RSA_WITH_RC4_128_SHA : + ssl->specs.bulk_cipher_algorithm = rc4; + ssl->specs.cipher_type = stream; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = rsa_kea; + ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.key_size = RC4_KEY_SIZE; + ssl->specs.iv_size = 0; + ssl->specs.block_size = 0; + + break; +#endif + +#ifdef BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA + case TLS_NTRU_RSA_WITH_RC4_128_SHA : + ssl->specs.bulk_cipher_algorithm = rc4; + ssl->specs.cipher_type = stream; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ntru_kea; + ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.key_size = RC4_KEY_SIZE; + ssl->specs.iv_size = 0; + ssl->specs.block_size = 0; + + break; +#endif + +#ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5 + case SSL_RSA_WITH_RC4_128_MD5 : + ssl->specs.bulk_cipher_algorithm = rc4; + ssl->specs.cipher_type = stream; + ssl->specs.mac_algorithm = md5_mac; + ssl->specs.kea = rsa_kea; + ssl->specs.hash_size = MD5_DIGEST_SIZE; + ssl->specs.pad_size = PAD_MD5; + ssl->specs.key_size = RC4_KEY_SIZE; + ssl->specs.iv_size = 0; + ssl->specs.block_size = 0; + + break; +#endif + +#ifdef BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA + case SSL_RSA_WITH_3DES_EDE_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = triple_des; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = rsa_kea; + ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.key_size = DES3_KEY_SIZE; + ssl->specs.block_size = DES_BLOCK_SIZE; + ssl->specs.iv_size = DES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA + case TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = triple_des; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ntru_kea; + ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.key_size = DES3_KEY_SIZE; + ssl->specs.block_size = DES_BLOCK_SIZE; + ssl->specs.iv_size = DES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA + case TLS_RSA_WITH_AES_128_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = rsa_kea; + ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA + case TLS_NTRU_RSA_WITH_AES_128_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ntru_kea; + ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA + case TLS_RSA_WITH_AES_256_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = rsa_kea; + ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA + case TLS_NTRU_RSA_WITH_AES_256_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ntru_kea; + ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA + case TLS_PSK_WITH_AES_128_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = psk_kea; + ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + ssl->options.usingPSK_cipher = 1; + break; +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA + case TLS_PSK_WITH_AES_256_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = psk_kea; + ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + ssl->options.usingPSK_cipher = 1; + break; +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA + case TLS_DHE_RSA_WITH_AES_128_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + case TLS_DHE_RSA_WITH_AES_256_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_RSA_WITH_HC_128_CBC_MD5 + case TLS_RSA_WITH_HC_128_CBC_MD5 : + ssl->specs.bulk_cipher_algorithm = hc128; + ssl->specs.cipher_type = stream; + ssl->specs.mac_algorithm = md5_mac; + ssl->specs.kea = rsa_kea; + ssl->specs.hash_size = MD5_DIGEST_SIZE; + ssl->specs.pad_size = PAD_MD5; + ssl->specs.key_size = HC_128_KEY_SIZE; + ssl->specs.block_size = 0; + ssl->specs.iv_size = HC_128_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_RSA_WITH_HC_128_CBC_SHA + case TLS_RSA_WITH_HC_128_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = hc128; + ssl->specs.cipher_type = stream; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = rsa_kea; + ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.key_size = HC_128_KEY_SIZE; + ssl->specs.block_size = 0; + ssl->specs.iv_size = HC_128_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_RSA_WITH_RABBIT_CBC_SHA + case TLS_RSA_WITH_RABBIT_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = rabbit; + ssl->specs.cipher_type = stream; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = rsa_kea; + ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.key_size = RABBIT_KEY_SIZE; + ssl->specs.block_size = 0; + ssl->specs.iv_size = RABBIT_IV_SIZE; + + break; +#endif + + default: + return UNSUPPORTED_SUITE; + } + } /* ECC / Normal suites else */ + + /* set TLS if it hasn't been turned off */ + if (ssl->version.major == 3 && ssl->version.minor >= 1) { +#ifndef NO_TLS + ssl->options.tls = 1; + ssl->hmac = TLS_hmac; + if (ssl->version.minor >= 2) + ssl->options.tls1_1 = 1; +#endif + } + +#ifdef CYASSL_DTLS + if (ssl->options.dtls) + ssl->hmac = TLS_hmac; +#endif + + return 0; +} + + +enum KeyStuff { + MASTER_ROUNDS = 3, + PREFIX = 3, /* up to three letters for master prefix */ + KEY_PREFIX = 7 /* up to 7 prefix letters for key rounds */ + + +}; + + +/* true or false, zero for error */ +static int SetPrefix(byte* sha_input, int index) +{ + switch (index) { + case 0: + XMEMCPY(sha_input, "A", 1); + break; + case 1: + XMEMCPY(sha_input, "BB", 2); + break; + case 2: + XMEMCPY(sha_input, "CCC", 3); + break; + case 3: + XMEMCPY(sha_input, "DDDD", 4); + break; + case 4: + XMEMCPY(sha_input, "EEEEE", 5); + break; + case 5: + XMEMCPY(sha_input, "FFFFFF", 6); + break; + case 6: + XMEMCPY(sha_input, "GGGGGGG", 7); + break; + default: + return 0; + } + return 1; +} + + +static int SetKeys(Ciphers* encrypt, Ciphers* decrypt, Keys* keys, + CipherSpecs* specs, byte side) +{ +#ifdef BUILD_ARC4 + word32 sz = specs->key_size; + if (specs->bulk_cipher_algorithm == rc4) { + if (side == CLIENT_END) { + Arc4SetKey(&encrypt->arc4, keys->client_write_key, sz); + Arc4SetKey(&decrypt->arc4, keys->server_write_key, sz); + } + else { + Arc4SetKey(&encrypt->arc4, keys->server_write_key, sz); + Arc4SetKey(&decrypt->arc4, keys->client_write_key, sz); + } + } +#endif + +#ifdef BUILD_HC128 + if (specs->bulk_cipher_algorithm == hc128) { + if (side == CLIENT_END) { + Hc128_SetKey(&encrypt->hc128, keys->client_write_key, + keys->client_write_IV); + Hc128_SetKey(&decrypt->hc128, keys->server_write_key, + keys->server_write_IV); + } + else { + Hc128_SetKey(&encrypt->hc128, keys->server_write_key, + keys->server_write_IV); + Hc128_SetKey(&decrypt->hc128, keys->client_write_key, + keys->client_write_IV); + } + } +#endif + +#ifdef BUILD_RABBIT + if (specs->bulk_cipher_algorithm == rabbit) { + if (side == CLIENT_END) { + RabbitSetKey(&encrypt->rabbit, keys->client_write_key, + keys->client_write_IV); + RabbitSetKey(&decrypt->rabbit, keys->server_write_key, + keys->server_write_IV); + } + else { + RabbitSetKey(&encrypt->rabbit, keys->server_write_key, + keys->server_write_IV); + RabbitSetKey(&decrypt->rabbit, keys->client_write_key, + keys->client_write_IV); + } + } +#endif + +#ifdef BUILD_DES3 + if (specs->bulk_cipher_algorithm == triple_des) { + if (side == CLIENT_END) { + Des3_SetKey(&encrypt->des3, keys->client_write_key, + keys->client_write_IV, DES_ENCRYPTION); + Des3_SetKey(&decrypt->des3, keys->server_write_key, + keys->server_write_IV, DES_DECRYPTION); + } + else { + Des3_SetKey(&encrypt->des3, keys->server_write_key, + keys->server_write_IV, DES_ENCRYPTION); + Des3_SetKey(&decrypt->des3, keys->client_write_key, + keys->client_write_IV, DES_DECRYPTION); + } + } +#endif + +#ifdef BUILD_AES + if (specs->bulk_cipher_algorithm == aes) { + if (side == CLIENT_END) { + AesSetKey(&encrypt->aes, keys->client_write_key, + specs->key_size, keys->client_write_IV, + AES_ENCRYPTION); + AesSetKey(&decrypt->aes, keys->server_write_key, + specs->key_size, keys->server_write_IV, + AES_DECRYPTION); + } + else { + AesSetKey(&encrypt->aes, keys->server_write_key, + specs->key_size, keys->server_write_IV, + AES_ENCRYPTION); + AesSetKey(&decrypt->aes, keys->client_write_key, + specs->key_size, keys->client_write_IV, + AES_DECRYPTION); + } + } +#endif + + keys->sequence_number = 0; + keys->peer_sequence_number = 0; + keys->encryptionOn = 0; + + return 0; +} + + +/* TLS can call too */ +int StoreKeys(SSL* ssl, const byte* keyData) +{ + int sz = ssl->specs.hash_size, i; + + XMEMCPY(ssl->keys.client_write_MAC_secret, keyData, sz); + i = sz; + XMEMCPY(ssl->keys.server_write_MAC_secret,&keyData[i], sz); + i += sz; + + sz = ssl->specs.key_size; + XMEMCPY(ssl->keys.client_write_key, &keyData[i], sz); + i += sz; + XMEMCPY(ssl->keys.server_write_key, &keyData[i], sz); + i += sz; + + sz = ssl->specs.iv_size; + XMEMCPY(ssl->keys.client_write_IV, &keyData[i], sz); + i += sz; + XMEMCPY(ssl->keys.server_write_IV, &keyData[i], sz); + + return SetKeys(&ssl->encrypt, &ssl->decrypt, &ssl->keys, &ssl->specs, + ssl->options.side); +} + + +int DeriveKeys(SSL* ssl) +{ + int length = 2 * ssl->specs.hash_size + + 2 * ssl->specs.key_size + + 2 * ssl->specs.iv_size; + int rounds = (length + MD5_DIGEST_SIZE - 1 ) / MD5_DIGEST_SIZE, i; + + byte shaOutput[SHA_DIGEST_SIZE]; + byte md5Input[SECRET_LEN + SHA_DIGEST_SIZE]; + byte shaInput[KEY_PREFIX + SECRET_LEN + 2 * RAN_LEN]; + + Md5 md5; + Sha sha; + + byte keyData[KEY_PREFIX * MD5_DIGEST_SIZE]; /* max size */ + + InitMd5(&md5); + InitSha(&sha); + + XMEMCPY(md5Input, ssl->arrays.masterSecret, SECRET_LEN); + + for (i = 0; i < rounds; ++i) { + int j = i + 1; + int idx = j; + + if (!SetPrefix(shaInput, i)) { + return PREFIX_ERROR; + } + + XMEMCPY(shaInput + idx, ssl->arrays.masterSecret, SECRET_LEN); + idx += SECRET_LEN; + XMEMCPY(shaInput + idx, ssl->arrays.serverRandom, RAN_LEN); + idx += RAN_LEN; + XMEMCPY(shaInput + idx, ssl->arrays.clientRandom, RAN_LEN); + idx += RAN_LEN; + + ShaUpdate(&sha, shaInput, sizeof(shaInput) - KEY_PREFIX + j); + ShaFinal(&sha, shaOutput); + + XMEMCPY(&md5Input[SECRET_LEN], shaOutput, SHA_DIGEST_SIZE); + Md5Update(&md5, md5Input, sizeof(md5Input)); + Md5Final(&md5, keyData + i * MD5_DIGEST_SIZE); + } + + return StoreKeys(ssl, keyData); +} + + +void CleanPreMaster(SSL* ssl) +{ + int i, sz = ssl->arrays.preMasterSz; + + for (i = 0; i < sz; i++) + ssl->arrays.preMasterSecret[i] = 0; + + RNG_GenerateBlock(&ssl->rng, ssl->arrays.preMasterSecret, sz); + + for (i = 0; i < sz; i++) + ssl->arrays.preMasterSecret[i] = 0; + +} + + +/* Create and store the master secret see page 32, 6.1 */ +int MakeMasterSecret(SSL* ssl) +{ + byte shaOutput[SHA_DIGEST_SIZE]; + byte md5Input[ENCRYPT_LEN + SHA_DIGEST_SIZE]; + byte shaInput[PREFIX + ENCRYPT_LEN + 2 * RAN_LEN]; + int i, ret; + word32 idx; + word32 pmsSz = ssl->arrays.preMasterSz; + + Md5 md5; + Sha sha; + +#ifdef SHOW_SECRETS + { + int j; + printf("pre master secret: "); + for (j = 0; j < pmsSz; j++) + printf("%02x", ssl->arrays.preMasterSecret[j]); + printf("\n"); + } +#endif + +#ifndef NO_TLS + if (ssl->options.tls) return MakeTlsMasterSecret(ssl); +#endif + + InitMd5(&md5); + InitSha(&sha); + + XMEMCPY(md5Input, ssl->arrays.preMasterSecret, pmsSz); + + for (i = 0; i < MASTER_ROUNDS; ++i) { + byte prefix[PREFIX]; + if (!SetPrefix(prefix, i)) { + return PREFIX_ERROR; + } + + idx = 0; + XMEMCPY(shaInput, prefix, i + 1); + idx += i + 1; + + XMEMCPY(shaInput + idx, ssl->arrays.preMasterSecret, pmsSz); + idx += pmsSz; + XMEMCPY(shaInput + idx, ssl->arrays.clientRandom, RAN_LEN); + idx += RAN_LEN; + XMEMCPY(shaInput + idx, ssl->arrays.serverRandom, RAN_LEN); + idx += RAN_LEN; + ShaUpdate(&sha, shaInput, idx); + ShaFinal(&sha, shaOutput); + + idx = pmsSz; /* preSz */ + XMEMCPY(md5Input + idx, shaOutput, SHA_DIGEST_SIZE); + idx += SHA_DIGEST_SIZE; + Md5Update(&md5, md5Input, idx); + Md5Final(&md5, &ssl->arrays.masterSecret[i * MD5_DIGEST_SIZE]); + } + +#ifdef SHOW_SECRETS + { + int i; + printf("master secret: "); + for (i = 0; i < SECRET_LEN; i++) + printf("%02x", ssl->arrays.masterSecret[i]); + printf("\n"); + } +#endif + + ret = DeriveKeys(ssl); + CleanPreMaster(ssl); + + return ret; +} + + + + -- cgit v1.2.3-54-g00ecf