wtls_statesupport.c
资源名称:gateway-1.2.1 [点击查看]
上传用户:gzpyjq
上传日期:2013-01-31
资源大小:1852k
文件大小:29k
源码类别:
手机WAP编程
开发平台:
WINDOWS
- /*
- * wtls_statesupport.c
- *
- * 2001 Nick Clarey, Yann Muller for 3G LAB
- */
- #include "gwlib/gwlib.h"
- #if (HAVE_WTLS_OPENSSL)
- #include <openssl/x509.h>
- #ifndef NO_RC5
- #include <openssl/rc5.h>
- #else
- #error "your OpenSSL installation lacks RC5 algorithm support"
- #endif
- #include "wtls_statesupport.h"
- #define BLOCKLENGTH 64
- #define INNERPAD 0x36
- #define OUTERPAD 0x5C
- extern X509* x509_cert;
- extern RSA* private_key;
- extern KeyExchangeSuite client_key_exchange_algo;
- extern PublicKeyAlgorithm public_key_algo;
- extern SignatureAlgorithm signature_algo;
- Octstr* wtls_hmac_hash(Octstr* key, Octstr* data, WTLSMachine* wtls_machine);
- Octstr* wtls_hash(Octstr* inputData, WTLSMachine* wtls_machine);
- Octstr* wtls_encrypt_rc5(Octstr* data, WTLSMachine* wtls_machine);
- Octstr* wtls_decrypt_rc5(Octstr* encryptedData, WTLSMachine* wtls_machine);
- /* Add here the supported KeyExchangeSuites
- used by wtls_choose_clientkeyid */
- KeyExchangeSuite supportedKeyExSuite[] = { rsa_anon };
- Octstr* wtls_decrypt(Octstr* buffer, WTLSMachine* wtls_machine)
- {
- return wtls_decrypt_rc5(buffer,wtls_machine);
- }
- /* This function will convert our buffer into a completed GenericBlockCipher */
- Octstr* wtls_encrypt(Octstr* buffer, WTLSMachine* wtls_machine, int recordType)
- {
- Octstr* bufferCopy;
- Octstr* encryptedContent;
- Octstr* contentMac;
- Octstr* padding;
- Octstr* tempData;
- unsigned char* tempPadding;
- int paddingLength, contentLength, macSize, blockLength,
- sequenceNumber, bufferLength;
- int i;
- /* Copy our buffer */
- bufferCopy = octstr_duplicate(buffer);
- /* Get the MAC of the content */
- sequenceNumber = wtls_machine->server_seq_num;
- bufferLength = octstr_len(buffer);
- /* Copy the buffer in preparation for MAC calculation */
- tempData = octstr_create("");
- pack_int16(tempData, 0, sequenceNumber);
- octstr_append_char(tempData, recordType);
- pack_int16(tempData, octstr_len(tempData), bufferLength);
- octstr_append(tempData, buffer);
- /* Calculate the MAC */
- contentMac = wtls_hmac_hash(wtls_machine->server_write_MAC_secret, tempData ,wtls_machine);
- /* Calculate the padding length */
- contentLength = octstr_len(bufferCopy);
- macSize = hash_table[wtls_machine->mac_algorithm].mac_size;
- blockLength = bulk_table[wtls_machine->bulk_cipher_algorithm].block_size;
- paddingLength = (contentLength + macSize + 1) % (blockLength);
- /* Append the MAC to the bufferCopy */
- octstr_append(bufferCopy,contentMac);
- if (paddingLength > 0) {
- /* Pad with the paddingLength itself paddingLength times. Confused yet? */
- tempPadding = gw_malloc(paddingLength);
- for (i=0;i < paddingLength; i++) {
- /* You're probably really spaced out around now...
- see section 9.2.3.3 for more details... */
- tempPadding[i] = paddingLength;
- }
- octstr_append_data(bufferCopy, tempPadding, paddingLength);
- }
- /* Add the length byte */
- octstr_append_char(bufferCopy, paddingLength);
- /* Encrypt the content */
- encryptedContent = wtls_encrypt_rc5(bufferCopy,wtls_machine);
- return encryptedContent;
- }
- /* P_hash as described in WAP WTLS section 11.3.2 */
- Octstr* wtls_P_hash(Octstr* secret, Octstr* seed, int byteLength, WTLSMachine* wtls_machine)
- {
- Octstr *a;
- Octstr *aPrev;
- Octstr *aPlusSeed;
- Octstr *hashTemp;
- Octstr *hashedData;
- hashedData = octstr_create("");
- /* start with A(1) = HMAC_hash(secret, seed) */
- aPrev = octstr_duplicate(seed);
- do {
- /* A(i) */
- a = wtls_hmac_hash(secret, aPrev, wtls_machine);
- aPlusSeed = octstr_cat(a, seed);
- /* HMAC */
- hashTemp = wtls_hmac_hash(secret, aPlusSeed, wtls_machine);
- octstr_append(hashedData, hashTemp);
- octstr_destroy(hashTemp);
- /* Update a(i-1) */
- octstr_destroy(aPrev);
- aPrev = a;
- } while(octstr_len(hashedData) < byteLength);
- gw_free(aPlusSeed);
- return hashedData;
- }
- /* Pseudo Random Function (PRF) as described in WAP WTLS section 11.3.2 */
- Octstr* wtls_calculate_prf(Octstr* secret, Octstr* label,
- Octstr* seed, int byteLength, WTLSMachine* wtls_machine)
- {
- Octstr* returnOctstr;
- Octstr *labelPlusSeed;
- /* Create label + seed */
- labelPlusSeed = octstr_cat(label, seed);
- /* PRF(secret, label, seed) = P_hash(secret, label + seed) */
- returnOctstr = wtls_P_hash(secret, labelPlusSeed, byteLength, wtls_machine);
- /* Return the first nbytes of the hashed data */
- octstr_truncate(returnOctstr, byteLength);
- gw_free(labelPlusSeed);
- return returnOctstr;
- }
- /* MAC calculation */
- Octstr* wtls_hmac_hash(Octstr* key, Octstr* data, WTLSMachine* wtls_machine)
- {
- static unsigned char final_mac[1024];
- unsigned char *mac, *buffer, *keyString;
- int mac_len, bufferlen, keylen;
- Octstr *returnOctstr;
- buffer = octstr_get_cstr(data);
- bufferlen = octstr_len(data);
- keyString = octstr_get_cstr(key);
- keylen = octstr_len(key);
- mac = final_mac;
- switch (wtls_machine->mac_algorithm) {
- case SHA_0:
- /* no keyed MAC is calculated */
- /* So what do we return ? */
- break;
- case SHA_40:
- case SHA_80:
- case SHA_NOLIMIT:
- HMAC(EVP_sha1(), keyString, keylen,
- buffer, bufferlen,
- mac, &mac_len);
- break;
- case SHA_XOR_40:
- // dunno yet
- break;
- case MD5_40:
- case MD5_80:
- case MD5_NOLIMIT:
- HMAC(EVP_md5(), keyString, keylen,
- buffer, bufferlen,
- mac, &mac_len);
- break;
- }
- returnOctstr = octstr_create_from_data(mac, mac_len);
- }
- /* Not to be confused with octstr_hash, this applies the currently set hashing
- algorithm from wtls_machine to the supplied input data, returning a hashed
- Octstr. If it fails, it will return a NULL pointer */
- Octstr* wtls_hash(Octstr* inputData, WTLSMachine* wtls_machine)
- {
- int inputDataLength;
- int outputDataLength;
- unsigned char* outputDataTemp;
- unsigned char* inputDataTemp;
- unsigned char* tempPointer;
- Octstr* outputData;
- inputDataLength = octstr_len(inputData);
- outputDataLength = hash_table[wtls_machine->mac_algorithm].key_size;
- inputDataTemp = gw_malloc(inputDataLength);
- outputDataTemp = gw_malloc(outputDataLength);
- /* Copy the contents of inputData into inputDataTemp, ready for hashing */
- tempPointer = octstr_get_cstr(inputData);
- memcpy((void*) inputDataTemp, (void*)tempPointer, inputDataLength);
- /* Hash away! */
- // Here's where we need to hash on the selected algorithm, not just the SHA-1 algorithm
- //debug("wtls", 0, "mac algo %d", wtls_machine->mac_algorithm);
- switch (wtls_machine->mac_algorithm) {
- case SHA_0:
- /* no keyed MAC is calculated */
- // So what do we return ?
- break;
- case SHA_40:
- case SHA_80:
- case SHA_NOLIMIT:
- tempPointer = SHA1(inputDataTemp, inputDataLength, outputDataTemp);
- break;
- case SHA_XOR_40:
- // dunno yet
- break;
- case MD5_40:
- case MD5_80:
- case MD5_NOLIMIT:
- tempPointer = MD5(inputDataTemp, inputDataLength, outputDataTemp);
- break;
- }
- if (tempPointer == NULL){
- /* Pop out an error */
- }
- /* Get our output data setup */
- outputData = octstr_create_from_data(outputDataTemp,outputDataLength);
- /* some algorithms don't use the full length of H */
- octstr_truncate(outputData, hash_table[wtls_machine->mac_algorithm].mac_size);
- /* Delete our allocated memory */
- gw_free(outputDataTemp);
- gw_free(inputDataTemp);
- outputDataTemp = NULL;
- inputDataTemp = NULL;
- /* Return the outputData */
- return outputData;
- }
- Octstr* wtls_decrypt_rc5(Octstr* data, WTLSMachine* wtls_machine)
- {
- Octstr* encryptedData;
- Octstr* decryptedData;
- Octstr* duplicatedIv;
- unsigned char* output;
- unsigned char* input;
- unsigned char* iv;
- unsigned char* keyData;
- int keyLen;
- int ivLen;
- int dataLen;
- RC5_32_KEY* key = NULL;
- ivLen = bulk_table[wtls_machine->bulk_cipher_algorithm].iv_size;
- duplicatedIv = octstr_duplicate(wtls_machine->client_write_IV);
- iv = octstr_get_cstr(duplicatedIv);
- keyLen = bulk_table[wtls_machine->bulk_cipher_algorithm].key_material;
- keyData = octstr_get_cstr(wtls_machine->client_write_enc_key);
- dataLen = octstr_len(data);
- input = octstr_get_cstr(data);
- key = gw_malloc (sizeof(RC5_32_KEY));
- /* Key generation */
- RC5_32_set_key(key, keyLen, keyData, RC5_16_ROUNDS);
- /* Malloc our output */
- output = gw_malloc (dataLen);
- /* Encrypt the string */
- debug("wtls_statesupport",0,"About to decrypt: dataLen = %d, iv = %x", dataLen, iv);
- octstr_dump(data,0);
- RC5_32_cbc_encrypt(input, output, dataLen, key, iv, RC5_DECRYPT);
- debug("wtls_statesupport",0,"Decrypted");
- decryptedData = octstr_create_from_data(output, dataLen);
- octstr_dump(decryptedData,0);
- /* Encrypt it just to test */
- gw_free(output);
- output = NULL;
- output = gw_malloc (dataLen);
- /* Ensure that we preserve the iv */
- octstr_destroy(duplicatedIv);
- duplicatedIv = octstr_duplicate(wtls_machine->client_write_IV);
- iv = octstr_get_cstr(duplicatedIv);
- octstr_get_many_chars(iv, wtls_machine->client_write_IV,0,ivLen);
- input = octstr_get_cstr(decryptedData);
- RC5_32_cbc_encrypt(input, output, dataLen, key, iv, RC5_ENCRYPT);
- encryptedData = octstr_create_from_data(output, dataLen);
- gw_free(output);
- output = NULL;
- octstr_destroy(duplicatedIv);
- return decryptedData;
- }
- Octstr* wtls_encrypt_rc5(Octstr* data, WTLSMachine* wtls_machine)
- {
- Octstr* encryptedData;
- Octstr* decryptedData;
- Octstr* duplicatedIv;
- unsigned char* output;
- unsigned char* input;
- unsigned char* iv;
- unsigned char* keyData;
- int keyLen;
- int ivLen;
- int dataLen;
- RC5_32_KEY* key = NULL;
- ivLen = bulk_table[wtls_machine->bulk_cipher_algorithm].iv_size;
- duplicatedIv = octstr_duplicate(wtls_machine->server_write_IV);
- iv = octstr_get_cstr(duplicatedIv);
- keyLen = bulk_table[wtls_machine->bulk_cipher_algorithm].key_material;
- keyData = octstr_get_cstr(wtls_machine->server_write_enc_key);
- dataLen = octstr_len(data);
- input = octstr_get_cstr(data);
- key = gw_malloc (sizeof(RC5_32_KEY));
- /* Key generation */
- debug("wtls_statesupport",0,"Key generation");
- RC5_32_set_key(key, keyLen, keyData, RC5_16_ROUNDS);
- /* Malloc our output */
- output = gw_malloc (dataLen);
- /* Encrypt the string */
- RC5_32_cbc_encrypt(input, output, dataLen, key, iv, RC5_ENCRYPT);
- encryptedData = octstr_create_from_data(output, dataLen);
- /* Decrypt it just to test */
- gw_free(output);
- output = NULL;
- output = gw_malloc (dataLen);
- /* Ensure that we preserve the iv */
- octstr_destroy(duplicatedIv);
- duplicatedIv = octstr_duplicate(wtls_machine->server_write_IV);
- iv = octstr_get_cstr(duplicatedIv);
- octstr_get_many_chars(iv, wtls_machine->server_write_IV,0,ivLen);
- input = octstr_get_cstr(encryptedData);
- RC5_32_cbc_encrypt(input, output, dataLen, key, iv, RC5_DECRYPT);
- decryptedData = octstr_create_from_data(output, dataLen);
- gw_free(output);
- output = NULL;
- octstr_destroy(duplicatedIv);
- return encryptedData;
- }
- Octstr* wtls_decrypt_rsa(Octstr* encryptedData)
- {
- int numBytesWritten=0,numBytesToRead=0;
- Octstr *decryptedData=0;
- unsigned char* tempDecryptionBuffer=0;
- char* tempEncryptionPointer=0;
- /* Allocate some memory for our decryption buffer */
- tempDecryptionBuffer = gw_malloc(RSA_size(private_key));
- /* Calculate the number of bytes to read from encryptedData when decrypting */
- numBytesToRead = octstr_len(encryptedData);
- /* Don't write to this pointer. Ever ever ever. */
- tempEncryptionPointer = octstr_get_cstr(encryptedData);
- /* Decrypt the data in encryptedData */
- numBytesWritten = RSA_private_decrypt(numBytesToRead, tempEncryptionPointer,
- tempDecryptionBuffer, private_key, RSA_PKCS1_PADDING);
- if(numBytesWritten == -1) {
- tempEncryptionPointer += 2;
- numBytesToRead -= 2;
- numBytesWritten = RSA_private_decrypt(numBytesToRead, tempEncryptionPointer,
- tempDecryptionBuffer, private_key, RSA_PKCS1_PADDING);
- }
- /* Move the tempDecryptionBuffer to an Octstr */
- decryptedData = octstr_create_from_data(tempDecryptionBuffer,numBytesWritten);
- /* Deallocate the tempDecryptionBuffer */
- gw_free(tempDecryptionBuffer);
- tempDecryptionBuffer = NULL;
- debug("wtls",0, "Decrypted secret");
- octstr_dump( decryptedData, 0);
- /* Return the decrypted data */
- return decryptedData;
- }
- void wtls_decrypt_pdu_list(WTLSMachine *wtls_machine, List *pdu_list)
- {
- int i, listlen;
- Octstr* decryptedData = NULL;
- wtls_Payload *payload;
- listlen = list_len(pdu_list);
- for( i=0; i<listlen; i++) {
- payload = (wtls_Payload *)list_get(pdu_list, i);
- if(payload->cipher) {
- debug("wtls", 0, "Decrypting PDU %d", i);
- decryptedData = wtls_decrypt(payload->data, wtls_machine);
- /* replace the data */
- octstr_destroy(payload->data);
- payload->data = decryptedData;
- }
- else {
- debug("wtls", 0, "PDU %d is not encrypted.", i);
- }
- }
- }
- RSAPublicKey* wtls_get_rsapublickey(void)
- {
- RSA* rsaStructure=0;
- EVP_PKEY* publicKey=0;
- BIGNUM *modulus=0,*exponent=0;
- unsigned char* tempModulusStorage=0,*tempExponentStorage=0;
- int numbytes=0;
- RSAPublicKey* returnStructure=0;
- Octstr *octstrModulus=0, *octstrExponent=0;
- /* First, we need to extract the RSA structure from the X509 Cert */
- /* Get the EVP_PKEY structure from the X509 cert */
- publicKey = X509_PUBKEY_get(x509_cert->cert_info->key);
- /* Take said EVP_PKEY structure and get the RSA component */
- if (EVP_PKEY_type(publicKey->type) != EVP_PKEY_RSA)
- {
- return NULL;
- }
- else
- {
- rsaStructure = publicKey->pkey.rsa;
- }
- /* Then we need to grab the exponent component from the cert */
- exponent = rsaStructure->e;
- /* We need to allocate sufficient memory to hold the exponent */
- numbytes = BN_num_bytes(exponent);
- tempExponentStorage = gw_malloc(numbytes);
- /* Then we get the exponent */
- numbytes = BN_bn2bin(exponent, tempExponentStorage);
- /* And finally we convert the exponent to an Octstr */
- octstrExponent = octstr_create_from_data(tempExponentStorage,numbytes);
- /* Then we need to grab the modulus component from the cert */
- modulus = rsaStructure->n;
- /* We need to allocate sufficient memory to hold the modulus */
- numbytes = BN_num_bytes(modulus);
- tempModulusStorage = gw_malloc(numbytes);
- /* Then we get the modulus */
- numbytes = BN_bn2bin(modulus, tempModulusStorage);
- /* And finally we convert the modulus to an Octstr */
- octstrModulus = octstr_create_from_data(tempModulusStorage,numbytes);
- /* Put the components into our return structure */
- returnStructure = gw_malloc(sizeof(RSAPublicKey));
- returnStructure->rsa_exponent = octstrExponent;
- returnStructure->rsa_modulus = octstrModulus;
- /* And deallocate the memory allocated for holding the modulus */
- gw_free(tempModulusStorage);
- gw_free(tempExponentStorage);
- tempModulusStorage = NULL;
- tempExponentStorage = NULL;
- return returnStructure;
- }
- Octstr* wtls_get_certificate(void)
- {
- unsigned char** pp;
- unsigned char* ppStart;
- int amountWritten = 1260;
- Octstr* returnOctstr;
- debug("wtls_get_certificate",0,"x509_cert : %x", x509_cert);
- /* Convert the x509 certificate to DER-encoding */
- amountWritten =i2d_X509(x509_cert, NULL);
- debug("wtls_get_certificate",0,"amountWritten : %d", amountWritten);
- /* Allocate some memory for *pp */
- pp = (unsigned char**) gw_malloc(sizeof(unsigned char**));
- /* Allocate the memory and call the same function again?!!?
- What an original idea :-/ */
- ppStart = (unsigned char *) gw_malloc (sizeof(unsigned char)*amountWritten);
- debug("wtls_get_certificate",0,"x509_cert_DER_pre : %x", *pp);
- *pp = ppStart;
- amountWritten =i2d_X509(x509_cert, pp);
- /* And we do this, because otherwise *pp is pointing to the end of the buffer. Yay */
- *pp = ppStart;
- debug("wtls_get_certificate",0,"x509_cert_DER_post : %x", *pp);
- /* Convert the DER-encoded char string to an octstr */
- returnOctstr = octstr_create_from_data(*pp,amountWritten);
- /* Destroy the memory allocated temporarily above */
- gw_free(*pp);
- *pp = NULL;
- /* Destroy the memory allocated for pp as well */
- gw_free(pp);
- pp = NULL;
- /* Return the octstr */
- return returnOctstr;
- }
- /* Chooses a CipherSuite from the list provided by the client.
- Returns NULL if none is acceptable. */
- CipherSuite* wtls_choose_ciphersuite(List* ciphersuites) {
- CipherSuite* returnSuite = NULL;
- CipherSuite* currentCS = NULL;
- int i = 0;
- int listLen;
- listLen = list_len(ciphersuites);
- //returnSuite = gw_malloc(sizeof(CipherSuite));
- /* the first CS in the list */
- do {
- /* the next CS in the list */
- currentCS = list_get(ciphersuites, i);
- /* Check if we support this BulkCipher */
- if(currentCS->bulk_cipher_algo >= RC5_CBC_40 &&
- currentCS->bulk_cipher_algo <= IDEA_CBC) {
- /* Check if we support this MAC algsorithm */
- if(currentCS->mac_algo >= SHA_0 &&
- currentCS->mac_algo <= MD5_NOLIMIT) {
- /* We can use this CipherSuite then */
- returnSuite = currentCS;
- }
- }
- i++;
- } while(returnSuite == NULL && i < listLen);
- return returnSuite;
- }
- int isSupportedKeyEx(int keyExId) {
- int maxSupported;
- int i;
- int retCode = 0;
- maxSupported = sizeof(supportedKeyExSuite) / sizeof(KeyExchangeSuite);
- for(i = 0; i<maxSupported; i++) {
- if(keyExId == supportedKeyExSuite[i]) {
- retCode = 1;
- }
- }
- return retCode;
- }
- int wtls_choose_clientkeyid(List* clientKeyIds) {
- int returnKey = 0;
- KeyExchangeId *currentKeyId = NULL;
- int i = 0;
- int listLen;
- listLen = list_len(clientKeyIds);
- debug("wtls", 0, "listLen = %d", listLen);
- do {
- currentKeyId = list_get(clientKeyIds, i);
- debug("wtls", 0, "Key %d", i);
- dump_key_exchange_id("wtls", 0, currentKeyId);
- /* check if the current key suite is supported */
- if(isSupportedKeyEx(currentKeyId->key_exchange_suite)) {
- returnKey = i+1;
- }
- i++;
- } while(returnKey == 0 && i < listLen);
- return returnKey;
- }
- int wtls_choose_snmode(int snmode)
- {
- return 2;
- }
- int wtls_choose_krefresh(int krefresh)
- {
- return 2;
- }
- Random* wtls_get_random(void)
- {
- Random* randomData;
- randomData = gw_malloc(sizeof(Random));
- randomData->gmt_unix_time = 0x0000;
- /* Yeah, I know, it's not very random */
- randomData->random_bytes = octstr_create("000000000000");
- return randomData;
- }
- int clienthellos_are_identical (List* pdu_list, List* last_received_packet)
- {
- return 0;
- }
- int certifcateverifys_are_identical (List* pdu_list, List* last_received_packet)
- {
- return 0;
- }
- int certificates_are_identical (List* pdu_list, List* last_received_packet)
- {
- return 0;
- }
- int clientkeyexchanges_are_identical (List* pdu_list, List* last_received_packet)
- {
- return 0;
- }
- int changecipherspecs_are_identical (List* pdu_list, List* last_received_packet)
- {
- return 0;
- }
- int finisheds_are_indentical (List* pdu_list, List* last_received_packet)
- {
- return 0;
- }
- int packet_contains_changecipherspec (List* pdu_list)
- {
- return 0;
- }
- int packet_contains_finished (List* pdu_list)
- {
- return 0;
- }
- int packet_contains_optional_stuff (List* pdu_list)
- {
- return 0;
- }
- int packet_contains_userdata (List* pdu_list)
- {
- /* FIXME: need to check if it is really Userdata !! */
- return 1;
- }
- int packet_contains_clienthello (List* pdu_list)
- {
- return 0;
- }
- int is_critical_alert (List* pdu_list)
- {
- return 0;
- }
- int is_warning_alert (List* pdu_list)
- {
- return 0;
- }
- /* go through the list of wtls_Payloads and add the data of any
- handshake message to wtls_machine->handshake_data */
- void add_all_handshake_data(WTLSMachine *wtls_machine, List *pdu_list)
- {
- long i, listlen;
- wtls_Payload *payload;
- gw_assert(pdu_list != NULL);
- listlen = list_len(pdu_list);
- debug("wtls", 0,"adding handshake data from %d PDU(s)", listlen);
- for(i=0; i<listlen; i++) {
- payload = (wtls_Payload *)list_get(pdu_list, i);
- if(payload->type == Handshake_PDU) {
- octstr_insert(wtls_machine->handshake_data, payload->data,
- octstr_len(wtls_machine->handshake_data));
- debug("wtls", 0, "Data from PDU %d:", i);
- octstr_dump(payload->data, 2);
- }
- }
- }
- void calculate_server_key_block(WTLSMachine *wtls_machine)
- {
- Octstr* concatenatedRandoms=0;
- Octstr* labelMaster=0;
- Octstr* key_block;
- Octstr* final_server_write_enc_key = NULL;
- Octstr* final_server_write_IV = NULL;
- Octstr* emptySecret = NULL;
- /* Concatenate our random data */
- concatenatedRandoms = octstr_create("");
- pack_int16(concatenatedRandoms, 0, wtls_machine->server_seq_num);
- octstr_append(concatenatedRandoms, wtls_machine->server_random);
- octstr_append(concatenatedRandoms, wtls_machine->client_random);
- /* Calculate the key_block */
- labelMaster = octstr_create("server expansion");
- key_block = wtls_calculate_prf(wtls_machine->master_secret, labelMaster,
- concatenatedRandoms,
- hash_table[wtls_machine->mac_algorithm].key_size
- + bulk_table[wtls_machine->bulk_cipher_algorithm].key_material
- + bulk_table[wtls_machine->bulk_cipher_algorithm].iv_size,
- wtls_machine );
- octstr_destroy(labelMaster);
- labelMaster = NULL;
- octstr_destroy(concatenatedRandoms);
- concatenatedRandoms = NULL;
- /* Break the key_block in its 3 parts */
- wtls_machine->server_write_MAC_secret = octstr_copy(key_block, 0, hash_table[wtls_machine->mac_algorithm].key_size);
- octstr_delete(key_block, 0, hash_table[wtls_machine->mac_algorithm].key_size);
- wtls_machine->server_write_enc_key = octstr_copy(key_block, 0, bulk_table[wtls_machine->bulk_cipher_algorithm].key_material);
- octstr_delete(key_block, 0, bulk_table[wtls_machine->bulk_cipher_algorithm].key_material);
- wtls_machine->server_write_IV = octstr_copy(key_block, 0, bulk_table[wtls_machine->bulk_cipher_algorithm].iv_size);
- /* Additional calculations for exportable encryption algos */
- if(bulk_table[wtls_machine->bulk_cipher_algorithm].is_exportable == EXPORTABLE) {
- concatenatedRandoms = octstr_cat(wtls_machine->client_random, wtls_machine->server_random);
- labelMaster = octstr_create("server write key");
- final_server_write_enc_key = wtls_calculate_prf(wtls_machine->server_write_enc_key, labelMaster,
- concatenatedRandoms,
- bulk_table[wtls_machine->bulk_cipher_algorithm].key_material,
- wtls_machine);
- octstr_destroy(labelMaster);
- labelMaster = NULL;
- octstr_destroy(concatenatedRandoms);
- concatenatedRandoms = NULL;
- octstr_destroy(wtls_machine->server_write_enc_key);
- wtls_machine->server_write_enc_key = final_server_write_enc_key;
- final_server_write_enc_key = NULL;
- concatenatedRandoms = octstr_create("");
- octstr_append_char(concatenatedRandoms, wtls_machine->server_seq_num);
- octstr_append(concatenatedRandoms, wtls_machine->client_random);
- octstr_append(concatenatedRandoms, wtls_machine->server_random);
- emptySecret = octstr_create("");
- final_server_write_IV = wtls_calculate_prf(emptySecret, labelMaster,
- concatenatedRandoms,
- bulk_table[wtls_machine->bulk_cipher_algorithm].iv_size,
- wtls_machine);
- octstr_destroy(labelMaster);
- labelMaster = NULL;
- octstr_destroy(concatenatedRandoms);
- concatenatedRandoms = NULL;
- }
- }
- void calculate_client_key_block(WTLSMachine *wtls_machine) {
- Octstr* concatenatedRandoms=0;
- Octstr* key_block;
- Octstr* final_client_write_enc_key = NULL;
- Octstr* final_client_write_IV = NULL;
- Octstr* emptySecret = NULL;
- Octstr* labelMaster=0;
- /* Concatenate our random data */
- concatenatedRandoms = octstr_create("");
- pack_int16(concatenatedRandoms, 0,wtls_machine->client_seq_num);
- octstr_append(concatenatedRandoms, wtls_machine->server_random);
- octstr_append(concatenatedRandoms, wtls_machine->client_random);
- /* Calculate the key_block */
- labelMaster = octstr_create("client expansion");
- key_block = wtls_calculate_prf(wtls_machine->master_secret, labelMaster,
- concatenatedRandoms,
- hash_table[wtls_machine->mac_algorithm].key_size
- + bulk_table[wtls_machine->bulk_cipher_algorithm].key_material
- + bulk_table[wtls_machine->bulk_cipher_algorithm].iv_size,
- wtls_machine );
- octstr_destroy(labelMaster);
- labelMaster = NULL;
- octstr_destroy(concatenatedRandoms);
- concatenatedRandoms = NULL;
- /* Break the key_block in its 3 parts */
- wtls_machine->client_write_MAC_secret = octstr_copy(key_block, 0, hash_table[wtls_machine->mac_algorithm].key_size);
- octstr_delete(key_block, 0, hash_table[wtls_machine->mac_algorithm].key_size);
- wtls_machine->client_write_enc_key = octstr_copy(key_block, 0, bulk_table[wtls_machine->bulk_cipher_algorithm].key_material);
- octstr_delete(key_block, 0, bulk_table[wtls_machine->bulk_cipher_algorithm].key_material);
- wtls_machine->client_write_IV = octstr_copy(key_block, 0, bulk_table[wtls_machine->bulk_cipher_algorithm].iv_size);
- /* Additional calculations for exportable encryption algos */
- if(bulk_table[wtls_machine->bulk_cipher_algorithm].is_exportable == EXPORTABLE) {
- concatenatedRandoms = octstr_cat(wtls_machine->client_random, wtls_machine->server_random);
- labelMaster = octstr_create("client write key");
- final_client_write_enc_key = wtls_calculate_prf(wtls_machine->client_write_enc_key, labelMaster,
- concatenatedRandoms,
- bulk_table[wtls_machine->bulk_cipher_algorithm].key_material,
- wtls_machine);
- octstr_destroy(labelMaster);
- labelMaster = NULL;
- octstr_destroy(wtls_machine->client_write_enc_key);
- wtls_machine->client_write_enc_key = final_client_write_enc_key;
- final_client_write_enc_key = NULL;
- octstr_destroy(labelMaster);
- labelMaster = NULL;
- octstr_destroy(concatenatedRandoms);
- concatenatedRandoms = NULL;
- emptySecret = octstr_create("");
- final_client_write_IV = wtls_calculate_prf(emptySecret, labelMaster,
- concatenatedRandoms,
- bulk_table[wtls_machine->bulk_cipher_algorithm].iv_size,
- wtls_machine);
- octstr_destroy(labelMaster);
- labelMaster = NULL;
- octstr_destroy(concatenatedRandoms);
- concatenatedRandoms = NULL;
- }
- }
- #endif