summaryrefslogtreecommitdiff
path: root/release/src/router/cyassl/src/keys.c
diff options
context:
space:
mode:
Diffstat (limited to 'release/src/router/cyassl/src/keys.c')
-rw-r--r--release/src/router/cyassl/src/keys.c751
1 files changed, 751 insertions, 0 deletions
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 <stdio.h>
+#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;
+}
+
+
+
+