#ifndef cp_secu_secu_h #define cp_secu_secu_h /* Cesar project {{{ * * Copyright (C) 2008 Spidcom * * <<>> * * }}} */ /** * \file cp/secu/secu.h * \brief Security related functions (crypto, ...). * \ingroup cp/secu */ #include "lib/swap.h" #include "cp/types.h" #include "cp/secu/defs.h" #include "cp/secu/pbkdf1.h" #include "cp/secu/inc/openssl_aes.h" #include "lib/rnd.h" #include #define GET_UINT32(n,b,i) \ { \ (n) = ( (u32) (b)[(i) ] ) \ | ( (u32) (b)[(i) + 1] << 8 ) \ | ( (u32) (b)[(i) + 2] << 16 ) \ | ( (u32) (b)[(i) + 3] << 24 ); \ } #define PUT_UINT32(n,b,i) \ { \ (b)[(i) ] = (u8) ( (n) ); \ (b)[(i) + 1] = (u8) ( (n) >> 8 ); \ (b)[(i) + 2] = (u8) ( (n) >> 16 ); \ (b)[(i) + 3] = (u8) ( (n) >> 24 ); \ } typedef AES_KEY cp_secu_aes_t; /** Data associated with a protocol run. */ struct cp_secu_protocol_run_t { /** Protocol identifier. */ u8 pid; /** Protocol message number. */ u8 pmn; /** Protocol run number. */ u16 prn; /** My nonce. */ u32 my_nonce; /** Other STA nonce. */ u32 your_nonce; }; typedef struct cp_secu_protocol_run_t cp_secu_protocol_run_t; /* Protocol ID interpretation can be found at * page 536 of HPAV specification V1.1. */ enum cp_secu_protocol_run_pid_t { CP_SECU_PROTOCOL_RUN_PID_AUTH_REQ_BY_NEW_STA, CP_SECU_PROTOCOL_RUN_PID_PROV_AUTH_STA_WITH_NEW_NEK, CP_SECU_PROTOCOL_RUN_PID_PROV_STA_WITH_NMK_USING_DAK, CP_SECU_PROTOCOL_RUN_PID_PROV_STA_WITH_NMK_USING_UKE, CP_SECU_PROTOCOL_RUN_PID_HLE_PROTOCOL, CP_SECU_PROTOCOL_RUN_PID_ND, }; typedef enum cp_secu_protocol_run_pid_t cp_secu_protocol_run_pid_t; /** Protocol run check result. */ enum cp_secu_protocol_run_check_result_t { /** Correspond to the next message in the protocol run. */ CP_SECU_PROTOCOL_RUN_CHECK_RESULT_NEXT, /** Correspond to the first message of a new protocol run. */ CP_SECU_PROTOCOL_RUN_CHECK_RESULT_NEW, /** Last message of the protocol run. */ CP_SECU_PROTOCOL_RUN_CHECK_RESULT_LAST, /** To know the size of enum. */ CP_SECU_PROTOCOL_RUN_CHECK_RESULT_NB, }; typedef enum cp_secu_protocol_run_check_result_t cp_secu_protocol_run_check_result_t; BEGIN_DECLS /** * Start a new protocol run and initialise the protocol run structure. * \param prun protocol run to initialise. * \param pid protocol identifier * \param rnd the lib random context to generate random number. */ void cp_secu_protocol_run_new (cp_secu_protocol_run_t *prun, u8 pid, lib_rnd_t *rnd); /** * Check a received protocol run against the current one. * \param prun current protocol run * \param prun_recv received protocol run * \param expected_result the expected result (i.e.: the current mode of the * PRUN exchange). See cp_secu_protocol_run_check_result_t. * \return true if the PRUN exchange is currently in the expected mode, false * otherwise. * * The current protocol run can be NULL if there is no current protocol run. * You can also use a pointer to an initialised protocol run if it is more * convenient. */ bool cp_secu_protocol_check (const cp_secu_protocol_run_t *prun, const cp_secu_protocol_run_t *prun_recv, const cp_secu_protocol_run_check_result_t expected_result); /** * Update a protocol run for the next message. * \param prun current protocol run * \param rnd the lib random context to generate random number. * \param last whether this is the last message * * Received protocol run should have been copied to the current one before * this call. */ void cp_secu_protocol_next (cp_secu_protocol_run_t *prun, lib_rnd_t *rnd, bool last); /** * Generate the NEK. * \param ctx the module context. * \param num a random number. * \param nb_iteration the number iterations needed. * \param output the generated key. * * This function call the PBKDF1 encryption function, nb_iteration should * correspond to the defines in the project i.e. CP_SECU_PBKDF1_ITERATION_NEK * for example to generate the NEK. */ void cp_secu_generate_key (cp_t *ctx, uint num, uint nb_iteration, cp_key_t *output_key); /** * Generate the keys * \param ctx the module context. * \param buffer the input buffer. * \param length the input buffer length. * \param salt the salt to use. * \return the key generated. */ extern inline cp_key_t cp_secu_generate_keys (cp_t *ctx, const u8 *buffer, uint length, cp_secu_salt_kind_t salt) { u8 output[sizeof (cp_key_t)]; cp_key_t keys; dbg_assert (buffer); dbg_assert (length); dbg_assert (salt < CP_SECU_SALT_KEY_NB); cp_secu_pbkdf1 (ctx, buffer, length, output, sizeof(output), salt, CP_SECU_PBKDF1_ITERATION); #if DEFS_BIG_ENDIAN GET_UINT32 (keys.key[0], output, 0); GET_UINT32 (keys.key[1], output, 4); GET_UINT32 (keys.key[2], output, 8); GET_UINT32 (keys.key[3], output, 12); #else memcpy (&keys.key, output, sizeof (cp_key_t)); #endif return keys; } /** * Generate the NMK from the NPW. * \param ctx the module context. * \param buffer the buffer containing the NPW * \param the buffer length. * * \warn the buffer provided will be replace by the hashed value. */ extern inline cp_key_t cp_secu_npw2nmk (cp_t *ctx, const u8 *buffer, uint length) { return cp_secu_generate_keys (ctx, buffer, length, CP_SECU_SALT_KEY_NMK_HS); } /** * Generate the DAK. * \param ctx the module context. * \param buffer the buffer containing the NPW * \param length the buffer length. * * \warn the buffer provided will be replace by the hashed value. */ extern inline cp_key_t cp_secu_dak_gen (cp_t *ctx, const u8 *buffer, uint length) { return cp_secu_generate_keys (ctx, buffer, length, CP_SECU_SALT_KEY_DAK); } /** * Generate the NID from the NMK and the security level. * \param ctx the module context. * \param buffer the buffer containing the NMK. * \param the Security level. * \return the NID computed. */ cp_nid_t cp_secu_nmk2nid(cp_t *ctx, cp_key_t nmk, u8 security_level); /** * Generate the TEK. * \param first the first hash key (the one in cm_get_key.req MME) * \param second the second hash key (the one in cm_get_key.cnf MME) * \param output the output buffer. */ void cp_secu_tek_gen (const u32 first[], const u32 second[], cp_key_t *output); /** * Generate some hash. * \param ctx the module context. * \param seed a random seed. * \param hash a buffer for the generated hash data. * \param hash_length hash buffer length (in bytes). */ void cp_secu_generate_hash (cp_t *ctx, u32 seed, u8 *hash, const uint hash_length); /** * Set the AES encryption key. * \param ctx the aes context. * \param key the Key to use. */ extern inline void cp_secu_aes_set_encrypt_key (cp_secu_aes_t *ctx, const cp_key_t key) { u32 tmp[4]; uint i; dbg_assert (ctx); for (i = 0; i < 4; i++) tmp[i] = swap32 (key.key[i]); AES_set_encrypt_key (tmp, ctx); } /** * Set the AES decryption key. * \param ctx the aes context. * \param key the Key to use. */ extern inline void cp_secu_aes_set_decrypt_key (cp_secu_aes_t *ctx, const cp_key_t key) { u32 tmp[4]; uint i; dbg_assert (ctx); for (i = 0; i < 4; i++) tmp[i] = swap32 (key.key[i]); AES_set_decrypt_key (tmp, ctx); } /** * Encrypt the input buffer. * \param ctx the aes context, * \param input the input buffer. * \param output the output buffer. */ extern inline void cp_secu_aes_encrypt (cp_secu_aes_t *ctx, const u32 *input, u32 *output) { u32 wb[4]; uint i; dbg_assert (ctx); dbg_assert (input); dbg_assert (output); for (i = 0; i < 4; i++) wb[i] = swap32 (input[i]); AES_encrypt (wb, output, ctx); for (i = 0; i < 4; i++) output[i] = swap32 (output[i]); } /** * Decrypt the input buffer. * \param ctx the aes context. * \param input the input buffer. * \param output the output buffer. */ extern inline void cp_secu_aes_decrypt ( cp_secu_aes_t *ctx, const u32 *input, u32 *output) { u32 wb[4]; uint i; dbg_assert (ctx); dbg_assert (input); dbg_assert (output); for (i = 0; i < 4; i++) wb[i] = swap32 (input[i]); AES_decrypt (wb, output, ctx); for (i = 0; i < 4; i++) output[i] = swap32 (output[i]); } /** * Encrypt a buffer. * \param ctx the module context. * \param aes_ctx the aes context. * \param iv the initializer vector. * \param input the input buffer. * \param output the output buffer. * \param length the input buffer length in bytes. */ void cp_secu_aes_cbc_encrypt (cp_t *ctx, cp_secu_aes_t *aes_ctx, u32 iv[4], const u32 *input, u32 *output, int length); /** * Decrypt a buffer. * \param ctx the module context. * \param aes_ctx the aes context. * \param iv the initializer vector. * \param input the input buffer. * \param output the output buffer. * \param length the input buffer length in bytes. */ void cp_secu_aes_cbc_decrypt (cp_t *ctx, cp_secu_aes_t *aes_ctx, u32 iv[4], const u32 *input, u32 *output, int length); /** * Generate the decryption key needed by hardware corresponding to the * provided encryption key. * \param enc encryption key * \param dec decryption key * * Keys are in the PB block encryption format which is different from the * payload encryption key format. */ void cp_secu_pbb_dec_gen (cp_key_t enc, cp_key_t *dec); END_DECLS #endif /* cp_secu_secu_h */