/**************************************************************************/ /* */ /* Copyright (c) Microsoft Corporation. All rights reserved. */ /* */ /* This software is licensed under the Microsoft Software License */ /* Terms for Microsoft Azure RTOS. Full text of the license can be */ /* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ /* and in the root directory of this software. */ /* */ /**************************************************************************/ /**************************************************************************/ /**************************************************************************/ /** */ /** NetX Crypto Component */ /** */ /** Transport Layer Security (TLS) */ /** */ /**************************************************************************/ /**************************************************************************/ #include "nx_crypto_tls_prf_1.h" /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_crypto_method_prf_1_init PORTABLE C */ /* 6.3.0 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function initializes the PRF crypto module with SHA-1. */ /* */ /* INPUT */ /* */ /* method Crypto Method Object */ /* key Key */ /* key_size_in_bits Size of the key, in bits */ /* handle Handle, specified by user */ /* crypto_metadata Metadata area */ /* crypto_metadata_size Size of the metadata area */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* None */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ /* 10-31-2023 Yanwu Cai Modified comment(s), */ /* resulting in version 6.3.0 */ /* */ /**************************************************************************/ NX_CRYPTO_KEEP UINT _nx_crypto_method_prf_1_init(struct NX_CRYPTO_METHOD_STRUCT *method, UCHAR *key, NX_CRYPTO_KEY_SIZE key_size_in_bits, VOID **handle, VOID *crypto_metadata, ULONG crypto_metadata_size) { NX_CRYPTO_TLS_PRF_1 *prf; NX_CRYPTO_PHASH *phash; NX_CRYPTO_PARAMETER_NOT_USED(handle); NX_CRYPTO_STATE_CHECK if ((method == NX_CRYPTO_NULL) || (key == NX_CRYPTO_NULL) || (crypto_metadata == NX_CRYPTO_NULL)) { return(NX_CRYPTO_PTR_ERROR); } /* Verify the metadata address is 4-byte aligned. */ if((((ULONG)crypto_metadata) & 0x3) != 0) { return(NX_CRYPTO_PTR_ERROR); } if(crypto_metadata_size < sizeof(NX_CRYPTO_TLS_PRF_1)) { return(NX_CRYPTO_PTR_ERROR); } /* Get our control block. */ prf = (NX_CRYPTO_TLS_PRF_1 *)crypto_metadata; phash = &(prf -> nx_secure_tls_prf_phash_info); /* Set the secret using the key value. */ phash -> nx_crypto_phash_secret = key; /* This is the length of secret in bytes actually */ phash -> nx_crypto_phash_secret_length = key_size_in_bits; return(NX_CRYPTO_SUCCESS); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_crypto_method_prf_1_cleanup PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function cleans up the crypto metadata. */ /* */ /* INPUT */ /* */ /* crypto_metadata Crypto metadata */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* NX_CRYPTO_MEMSET Set the memory */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ /* */ /**************************************************************************/ NX_CRYPTO_KEEP UINT _nx_crypto_method_prf_1_cleanup(VOID *crypto_metadata) { NX_CRYPTO_STATE_CHECK #ifdef NX_SECURE_KEY_CLEAR if (!crypto_metadata) return (NX_CRYPTO_SUCCESS); /* Clean up the crypto metadata. */ NX_CRYPTO_MEMSET(crypto_metadata, 0, sizeof(NX_CRYPTO_TLS_PRF_1)); #else NX_CRYPTO_PARAMETER_NOT_USED(crypto_metadata); #endif/* NX_SECURE_KEY_CLEAR */ return(NX_CRYPTO_SUCCESS); } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_crypto_method_prf_1_operation PORTABLE C */ /* 6.3.0 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function encrypts and decrypts a message using */ /* the PRF SHA-1 algorithm. */ /* */ /* INPUT */ /* */ /* op PRF operation */ /* handle Crypto handle */ /* method Cryption Method Object */ /* key Encryption Key */ /* key_size_in_bits Key size in bits */ /* input Input data */ /* input_length_in_byte Input data size */ /* iv_ptr Initial vector */ /* output Output buffer */ /* output_length_in_byte Output buffer size */ /* crypto_metadata Metadata area */ /* crypto_metadata_size Metadata area size */ /* packet_ptr Pointer to packet */ /* nx_crypto_hw_process_callback Callback function pointer */ /* */ /* OUTPUT */ /* */ /* status Completion status */ /* */ /* CALLS */ /* */ /* _nx_crypto_tls_prf_1 Implement the TLS PRF */ /* using SHA-1 */ /* */ /* CALLED BY */ /* */ /* Application Code */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), improved */ /* buffer length verification, */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ /* 10-31-2023 Yanwu Cai Modified comment(s), */ /* resulting in version 6.3.0 */ /* */ /**************************************************************************/ NX_CRYPTO_KEEP UINT _nx_crypto_method_prf_1_operation(UINT op, /* Encrypt, Decrypt, Authenticate */ VOID *handle, /* Crypto handler */ struct NX_CRYPTO_METHOD_STRUCT *method, UCHAR *key, NX_CRYPTO_KEY_SIZE key_size_in_bits, UCHAR *input, ULONG input_length_in_byte, UCHAR *iv_ptr, UCHAR *output, ULONG output_length_in_byte, VOID *crypto_metadata, ULONG crypto_metadata_size, VOID *packet_ptr, VOID (*nx_crypto_hw_process_callback)(VOID *packet_ptr, UINT status)) { UINT status, secret_len; UCHAR *secret_half_point; NX_CRYPTO_TLS_PRF_1 *prf; NX_CRYPTO_PHASH *phash; NX_CRYPTO_PARAMETER_NOT_USED(handle); NX_CRYPTO_PARAMETER_NOT_USED(iv_ptr); NX_CRYPTO_PARAMETER_NOT_USED(packet_ptr); NX_CRYPTO_PARAMETER_NOT_USED(nx_crypto_hw_process_callback); NX_CRYPTO_STATE_CHECK /* Verify the metadata address is 4-byte aligned. */ if((method == NX_CRYPTO_NULL) || (key == NX_CRYPTO_NULL) || (crypto_metadata == NX_CRYPTO_NULL) || ((((ULONG)crypto_metadata) & 0x3) != 0)) { return(NX_CRYPTO_PTR_ERROR); } if(crypto_metadata_size < sizeof(NX_CRYPTO_TLS_PRF_1)) { return(NX_CRYPTO_PTR_ERROR); } /* This must be a PRF operation. */ if (op != NX_CRYPTO_PRF) { return(NX_CRYPTO_NOT_SUCCESSFUL); } /* Get our control block. */ prf = (NX_CRYPTO_TLS_PRF_1 *)crypto_metadata; phash = &(prf -> nx_secure_tls_prf_phash_info); /* Install the label_seed_buffer to the phash structure as the buffer of phash seed. */ phash -> nx_crypto_phash_seed = prf -> nx_secure_tls_prf_label_seed_buffer; if ((key_size_in_bits + input_length_in_byte) > sizeof(prf -> nx_secure_tls_prf_label_seed_buffer)) { return(NX_CRYPTO_SIZE_ERROR); } /* Concatenate label and seed. */ NX_CRYPTO_MEMCPY(phash -> nx_crypto_phash_seed, key, key_size_in_bits); /* Use case of memcpy is verified. */ NX_CRYPTO_MEMCPY(&phash -> nx_crypto_phash_seed[key_size_in_bits], input, input_length_in_byte); /* Use case of memcpy is verified. */ phash -> nx_crypto_phash_seed_length = key_size_in_bits + input_length_in_byte; /* Install the temp_A_buffer to the phash structure. */ phash -> nx_crypto_phash_temp_A = prf -> nx_secure_tls_prf_temp_A_buffer; phash -> nx_crypto_phash_temp_A_size = sizeof(prf -> nx_secure_tls_prf_temp_A_buffer); /* Install metadata buffer for the hmac method. */ phash -> nx_crypto_hmac_metadata = prf -> nx_secure_tls_prf_hmac_metadata_area; phash -> nx_crypto_hmac_metadata_size = sizeof(prf -> nx_secure_tls_prf_hmac_metadata_area); /* Install the buffer for hmac output. */ phash -> nx_crypto_hmac_output = prf -> nx_secure_tls_prf_temp_hmac_output_buffer; phash -> nx_crypto_hmac_output_size = sizeof(prf -> nx_secure_tls_prf_temp_hmac_output_buffer); /* SHA1 first. */ /* Clear the output buffer for the generic phash routine will show the output by XOR. */ NX_CRYPTO_MEMSET(output, 0, output_length_in_byte); /* Install the hmac method to the phash structure. */ phash -> nx_crypto_hmac_method = &crypto_method_hmac_md5; /* Calculate secret half-length. */ secret_len = (phash -> nx_crypto_phash_secret_length + 1) / 2; /* Find the offset of the half-way point. If the size of the secret is not even, overlap the last byte of the first half and first byte of the second half. */ if (phash -> nx_crypto_phash_secret_length % 2) { /* Length is odd - overlap a byte. */ secret_half_point = &(phash -> nx_crypto_phash_secret[secret_len - 1]); } else { /* Evenly divisible, offset is just after the half-length. */ secret_half_point = &(phash -> nx_crypto_phash_secret[secret_len]); } /* Update secret length. */ phash -> nx_crypto_phash_secret_length = secret_len; status = _nx_crypto_phash(phash, output, output_length_in_byte); if (status) { return status; } /* Install the hmac method to the phash structure. */ phash -> nx_crypto_hmac_method = &crypto_method_hmac_sha1; /* Take use of the second half of the secret. */ phash -> nx_crypto_phash_secret = secret_half_point; /* Do not clear the output buffer this time. */ status = _nx_crypto_phash(phash, output, output_length_in_byte); return status; }