void pal_encode_amp_assoc(FsmContext *context, PalChannellist *connectedChannelList, PalChannellist *preferredChannelList, unifi_MACAddress *macAddress, PAL_CoexCapabilities *capabilities, CsrUint8 **data, CsrUint16 *len) { CsrUint8 *buffer; CsrUint8 i; USED_CHANNELS_LIST channelList; *data = CsrPmalloc(PAL_AMP_ASSOC_MAX_TOTAL_LENGTH); /* alloc memory big enough to hold the biggest assoc*/ buffer = *data; sme_trace_entry((TR_PAL_LM_LINK_FSM,"encode_amp_assoc")); encode_amp_assoc_mac_address(&buffer,macAddress->data); CsrMemSet(&channelList, 0, sizeof(USED_CHANNELS_LIST)); /* consider the preferred only if PAL has started the network (which means numChannels==1). * Otherwise regulatory domain can get the appropriate valid channel list */ if (1 == preferredChannelList->numChannels) { channelList.listChangedFlag = TRUE; channelList.Dott11_b_g_ChanList[0].chan_scan_mode = channelScanMode_active; channelList.Dott11_b_g_ChanList[0].chan_number = preferredChannelList->number[0]; } encode_amp_assoc_channel_list(context, &buffer, &channelList, AMP_ASSOC_PREFERRED_CHANNEL_LIST_TYPE); verify(TR_PAL_LM_LINK_FSM, (CsrUint16)(buffer-(*data))<=PAL_AMP_ASSOC_MAX_TOTAL_LENGTH); if (connectedChannelList && connectedChannelList->numChannels) { CsrMemSet(&channelList, 0, sizeof(USED_CHANNELS_LIST)); channelList.listChangedFlag = TRUE; for (i=0; i<connectedChannelList->numChannels && i<HIGHEST_80211_b_g_CHANNEL_NUM; i++) { channelList.Dott11_b_g_ChanList[i].chan_scan_mode = channelScanMode_active; channelList.Dott11_b_g_ChanList[i].chan_number = connectedChannelList->number[i]; } encode_amp_assoc_channel_list(context, &buffer,&channelList, AMP_ASSOC_CONNECTED_CHANNEL_TYPE); verify(TR_PAL_LM_LINK_FSM, (CsrUint16)(buffer-(*data))<=PAL_AMP_ASSOC_MAX_TOTAL_LENGTH); } encode_amp_assoc_capabilities(&buffer,capabilities); encode_amp_assoc_pal_version(&buffer); *len = (CsrUint16)(buffer-(*data)); verify(TR_PAL_LM_LINK_FSM,*len <= PAL_AMP_ASSOC_MAX_TOTAL_LENGTH); sme_trace_info((TR_PAL_LM_LINK_FSM,"encode_amp_assoc:encoded %d bytes",*len)); }
int main(int argc, char **argv) { /* Create the Application Context */ linuxContext = (LinuxUserSpaceContext*) CsrPmalloc(sizeof(LinuxUserSpaceContext)); CsrMemSet(linuxContext, 0x00, sizeof(LinuxUserSpaceContext)); linuxContext->mainData = (MainData*) CsrPmalloc(sizeof(MainData)); #ifdef IPC_IP getMainData(linuxContext)->ipIpcCon = NULL; #endif #ifdef IPC_CHARDEVICE getMainData(linuxContext)->charIpcCon = NULL; #endif /* Set Trace levels from the command line */ sme_trace_initialise((CsrUint32)argc, argv); /* Send the first trace message */ sme_trace_entry((TR_STARTUP_SAP, "%s(%d)", __FUNCTION__, argc)); /* Initialise SME and scheduling */ sme_schedule_init(linuxContext, argc, argv); fsm_schedule(linuxContext); return 0; }
/* -------------------------------------------------------------------------- * * Retrieves statistics on the operation of the payload manager subsystem */ void pld_get_stats(PldContext* context, PldStats *userStats) { require(TR_PAYLOAD_MGR, userStats != NULL); #ifdef SME_TRACE_ENABLE #ifdef FSM_MUTEX_ENABLE (void)CsrMutexLock(context->payloadLock); #endif CsrMemCpy(userStats, (void *)&context->stats, sizeof(context->stats)); #ifdef FSM_MUTEX_ENABLE (void)CsrMutexUnlock(context->payloadLock); #endif #else CsrMemSet(userStats, 0x00, sizeof(PldStats)); #endif }
void initKeyPair( CsrWpsContext *pCtx ) { CsrUint8 base[192]; CsrInt32 i, j; CsrInt32 clear_bytes = (1536 - keylen) / 8; CsrInt32 clear_bits = (1536 - keylen) % 8; CsrUint8 bit_mask, mask; CsrUint32 length; CsrMemSet(base, 0, sizeof(base)); base[191] = g; sme_trace_info((TR_SECURITY_LIB, "Private key length = %d", keylen)); CsrWifiSecurityRandom(pCtx->ePrvKey, sizeof(pCtx->ePrvKey)); for(i = 0; i < clear_bytes; i++) { pCtx->ePrvKey[i] = 0; } if(i < 192) { for(bit_mask = 0x80, j = 0; j < clear_bits; j++) /*lint !e681*/ { bit_mask >>= 1; } for(mask = 0, j = clear_bits; j < 8; j++) { mask |= bit_mask; bit_mask >>= 1; } sme_trace_info((TR_SECURITY_LIB, "Private key bit mask = 0x%02x", mask)); pCtx->ePrvKey[i] &= mask; } CsrCryptoModExp(base, sizeof(base), pCtx->ePrvKey, sizeof(pCtx->ePrvKey), prime, sizeof(prime), pCtx->ePubKey, &length); sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "WPS Enrollee Public Key", pCtx->ePubKey, sizeof(pCtx->ePubKey))); sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "WPS Enrollee Private Key", pCtx->ePrvKey, sizeof(pCtx->ePrvKey))); }
/*---------------------------------------------------------------------------*/ CsrUint8* ie_dot11n_generate_ht_cap_ie( CsrUint8 *pbuf) { sme_trace_debug((TR_IE_ACCESS, "ie_dot11n_generate_ht_cap_ie ")); CsrMemSet(pbuf, 0, IE_HT_CAPABILITIES__TOTAL_SIZE); /* pbuf[IE_DOT11N_HT_CAP__ID_OFFSET] = IE_DOT11N_ID_HT_CAPABILITIES; pbuf[IE_DOT11N_HT_CAP__LENGTH_OFFSET] = (IE_HT_CAPABILITIES__TOTAL_SIZE-2); */ /* remove the header size */ pbuf[0] = IE_DOT11N_ID_HT_CAPABILITIES; pbuf[1] = (IE_HT_CAPABILITIES__TOTAL_SIZE-2); /* remove the header size */ /* REMINDER: * The firmware will populate this IE, we just allocate the space */ sme_trace_hex((TR_IE_PRINT, TR_LVL_DEBUG, " data", pbuf, IE_HT_CAPABILITIES__TOTAL_SIZE)); return pbuf + IE_HT_CAPABILITIES__TOTAL_SIZE; }
/* -------------------------------------------------------------------------- * * Initialises the payload manager subsystem. */ PldContext* pld_init(CsrUint16 tableSize, CsrUint16 maxPayloads) { PldContext* context = (PldContext*)CsrPmalloc(sizeof(PldContext)); sme_trace_entry((TR_PAYLOAD_MGR, "pld_init() maxPayloads %d", maxPayloads)); /* Initialise the context */ #ifdef FSM_MUTEX_ENABLE (void)CsrMutexCreate(&context->payloadLock); #endif csr_list_init(&context->payloads); context->payloadMax = maxPayloads; context->payloadCount = 0; context->lastHandle = 0; /* handle 0 should never be used */ context->nextUsedHandle = PLDREFERENCEMASK; #ifdef SME_TRACE_ENABLE CsrMemSet(&context->stats, 0, sizeof(context->stats)); context->stats.maxPayloads = maxPayloads; #endif return context; }
/* * --------------------------------------------------------------------------- * parse_xbv1 * * Scan the firmware file to find the TLVs we are interested in. * Actions performed: * - check we support the file format version in VERF * Store these TLVs if we have a firmware image: * - SLTP Symbol Lookup Table Pointer * - FWDL firmware download segments * - FWOL firmware overlay segment * - VMEQ Register probe tests to verify matching h/w * Store these TLVs if we have a patch file: * - FWID the firmware build ID that this file patches * - PTDL The actual patches * * The structure pointed to by fwinfo is cleared and * 'fwinfo->mode' is set to 'unknown'. The 'fwinfo->mode' * variable is set to 'firmware' or 'patch' once we know which * sort of XBV file we have. * * Arguments: * readfn Pointer to function to call to read from the file. * dlpriv Opaque pointer arg to pass to readfn. * fwinfo Pointer to fwinfo struct to fill in. * * Returns: * CSR_RESULT_SUCCESS on success, CSR error code on failure * --------------------------------------------------------------------------- */ CsrResult xbv1_parse(card_t *card, fwreadfn_t readfn, void *dlpriv, xbv1_t *fwinfo) { ct_t ct; tag_t tag; xbv_stack_t stack; ct.dlpriv = dlpriv; ct.ioffset = 0; ct.iread = readfn; CsrMemSet(fwinfo, 0, sizeof(xbv1_t)); fwinfo->mode = xbv_unknown; /* File must start with XBV1 triplet */ if (read_tag(card, &ct, &tag) <= 0) { unifi_error(NULL, "File is not UniFi firmware\n"); return CSR_WIFI_HIP_RESULT_INVALID_VALUE; } DBG_TAG(tag.t_name); if (!TAG_EQ(tag.t_name, "XBV1")) { unifi_error(NULL, "File is not UniFi firmware (%s)\n", tag.t_name); return CSR_WIFI_HIP_RESULT_INVALID_VALUE; } stack.ptr = 0; stack.s[stack.ptr].container = xbv_xbv1; stack.s[stack.ptr].ioffset_end = XBV_MAX_OFFS; /* Now scan the file */ while (1) { CsrInt32 n; n = read_tag(card, &ct, &tag); if (n < 0) { unifi_error(NULL, "No tag\n"); return CSR_WIFI_HIP_RESULT_INVALID_VALUE; } if (n == 0) { /* End of file */ break; } DBG_TAG(tag.t_name); /* File format version */ if (TAG_EQ(tag.t_name, "VERF")) { CsrUint32 version; if (xbv_check(fwinfo, &stack, xbv_unknown, xbv_xbv1) || (tag.t_len != 2) || read_uint(card, &ct, &version, 2)) { return CSR_WIFI_HIP_RESULT_INVALID_VALUE; } if (version != 0) { unifi_error(NULL, "Unsupported firmware file version: %d.%d\n", version >> 8, version & 0xFF); return CSR_WIFI_HIP_RESULT_INVALID_VALUE; } }
static void sme_schedule_init(LinuxUserSpaceContext* context, int argc, char **argv) { CsrBool wifion = FALSE; CsrBool flightmode = FALSE; int i; #ifdef IPC_IP CsrUint32 ipc_portNumber = PORT_NUMBER_Q; #ifdef CSR_AMP_ENABLE CsrUint32 ipc_hciPortNumber = HCI_PORT_NUMBER_Q; CsrUint32 ipc_aclPortNumber = ACL_PORT_NUMBER_Q; #endif #endif #ifdef IPC_CHARDEVICE const char* connectStr = CHAR_DEVICE_Q; #endif sme_trace_entry((TR_FSM, "sme_schedule_init()")); CsrMemSet(&getMainData(linuxContext)->address, 0xFF, sizeof(unifi_MACAddress)); getMainData(linuxContext)->mibfiles.numElements = 0; getMainData(linuxContext)->mibfiles.dataList = (unifi_DataBlock*)CsrPmalloc(sizeof(unifi_DataBlock) * MAX_MIB_FILES); getMainData(linuxContext)->calibrationDataFile = NULL; getMainData(linuxContext)->calibrationData.length = 0; getMainData(linuxContext)->calibrationData.data = NULL; getMainData(linuxContext)->nextCaldataSaveTime = fsm_get_time_of_day_ms(context->fsmContext) + CALDATA_SAVE_INTERVAL_MS; getMainData(linuxContext)->exitOnError = FALSE; getMainData(linuxContext)->stopOnError = FALSE; #ifdef CSR_AMP_ENABLE context->palDataFsmContext = paldata_init(linuxContext); sme_install_wakeup_callback(context->palDataFsmContext, fsm_wakeup_callback); #endif /* Initialise basic constructs used by the SME */ context->fsmContext = sme_init(context, NULL); sme_install_wakeup_callback(context->fsmContext, fsm_wakeup_callback); #ifdef CSR_WIFI_NME_ENABLE context->nmeFsmContext = csr_wifi_nme_init(linuxContext, NULL); csr_wifi_nme_install_wakeup_callback(context->nmeFsmContext, fsm_wakeup_callback); #endif #ifdef FSM_DEBUG fsm_install_on_transition_callback(context->fsmContext, fsm_on_transition_trace_callback); fsm_install_unhandled_event_callback(context->fsmContext, fsm_on_unhandled_trace_callback); fsm_install_save_event_callback(context->fsmContext, fsm_on_saved_trace_callback); fsm_install_invalid_event_callback(context->fsmContext, fsm_on_invalid_trace_callback); fsm_install_ignore_event_callback(context->fsmContext, fsm_on_ignored_trace_callback); #ifdef CSR_WIFI_NME_ENABLE fsm_install_on_transition_callback(context->nmeFsmContext, nme_on_transition_trace_callback); fsm_install_unhandled_event_callback(context->nmeFsmContext, nme_on_unhandled_trace_callback); fsm_install_save_event_callback(context->nmeFsmContext, nme_on_saved_trace_callback); fsm_install_invalid_event_callback(context->nmeFsmContext, nme_on_invalid_trace_callback); fsm_install_ignore_event_callback(context->nmeFsmContext, nme_on_ignored_trace_callback); #endif #endif registerSignalHandlers(); /* If no args print the usage incase the user does not know what the help option is */ if (argc == 1) { print_usage(); } for (i = 1; i < argc; i++) { if (CsrStrNCmp(argv[i], "-ipc_port:", 10) == 0) { #ifdef IPC_IP ipc_portNumber = (CsrUint32)atoi(&argv[i][10]); sme_trace_info((TR_IPC, "sme_schedule_init() : IPC Port override -> %s :: %d", argv[i], ipc_portNumber)); #endif continue; } #ifdef CSR_AMP_ENABLE if (CsrStrNCmp(argv[i], "-ipc_hciport:", 13) == 0) { #ifdef IPC_IP ipc_hciPortNumber = (CsrUint32)atoi(&argv[i][13]); sme_trace_info((TR_IPC, "sme_schedule_init() : HCI IPC Port override -> %s :: %d", argv[i], ipc_hciPortNumber)); #endif continue; } if (CsrStrNCmp(argv[i], "-ipc_aclport:", 13) == 0) { #ifdef IPC_IP ipc_aclPortNumber = (CsrUint32)atoi(&argv[i][13]); sme_trace_info((TR_IPC, "sme_schedule_init() : ACL IPC Port override -> %s :: %d", argv[i], ipc_aclPortNumber)); #endif continue; } #endif /* TODO :: This is depricated... Remove! */ if (CsrStrNCmp(argv[i], "-ipc_connect=", 13) == 0) { #ifdef IPC_CHARDEVICE connectStr = &argv[i][13]; sme_trace_crit((TR_IPC, "sme_schedule_init() : -ipc_connect option is depricated. DO NOT USE!")); sme_trace_info((TR_IPC, "sme_schedule_init() : IPC Connect String -> %s :: %s", argv[i], connectStr)); #endif continue; } if (CsrStrNCmp(argv[i], "-dev=", 5) == 0) { #ifdef IPC_CHARDEVICE connectStr = &argv[i][5]; sme_trace_info((TR_IPC, "sme_schedule_init() : char device -> %s :: %s", argv[i], connectStr)); #endif continue; } if (CsrStrNCmp(argv[i], "-paldatadev=", 12) == 0) { continue; } #ifdef CSR_AMP_ENABLE if (CsrStrNCmp(argv[i], "-palselectchannel=", 18) == 0) { int len = CsrStrLen(argv[i]); char* str = (char*)CsrPmalloc(len); CsrMemCpy(str,&(argv[i][1]), len-1); str[len-1] = '\0'; sme_trace_info((TR_IPC, "sme_schedule_init() : pal channel to select -> %s :: %d , len-%d,str-%s", argv[i], (CsrUint8)atoi(&argv[i][18]),len,str)); unifi_dbg_cmd_req(context->fsmContext, str); continue; } if (CsrStrNCmp(argv[i], "-paldisableqos", 18) == 0) { int len = CsrStrLen(argv[i]); char* str = (char*)CsrPmalloc(len); CsrMemCpy(str,&(argv[i][1]), len-1); str[len-1] = '\0'; sme_trace_info((TR_IPC, "sme_schedule_init() : disable qos to select -%s , len-%d,str-%s", argv[i],len,str)); unifi_dbg_cmd_req(context->fsmContext, str); continue; } if (CsrStrNCmp(argv[i], "-paldisablesecurity", 18) == 0) { int len = CsrStrLen(argv[i]); char* str = (char*)CsrPmalloc(len); CsrMemCpy(str,&(argv[i][1]), len-1); str[len-1] = '\0'; sme_trace_info((TR_IPC, "sme_schedule_init() : disable qos to select -%s", argv[i])); unifi_dbg_cmd_req(context->fsmContext, str); continue; } #endif if (CsrStrNCmp(argv[i], "-flightmode", 11) == 0) { flightmode = TRUE; sme_trace_info((TR_IPC, "sme_schedule_init() : unifi_mgt_wifi_flightmode_req will be sent on connect -> %s", argv[i])); continue; } if (CsrStrNCmp(argv[i], "-wifion", 7) == 0) { wifion = TRUE; sme_trace_info((TR_IPC, "sme_schedule_init() : unifi_mgt_wifi_on_req will be sent on connect -> %s", argv[i])); continue; } if (CsrStrNCmp(argv[i], "-mac=", 5) == 0) { loadMacAddress(&argv[i][5], &getMainData(linuxContext)->address); sme_trace_info((TR_IPC, "sme_schedule_init() : macAddress file -> %s", argv[i])); sme_trace_info((TR_IPC, "sme_schedule_init() : macAddress -> %s", trace_unifi_MACAddress(getMainData(linuxContext)->address, getMainData(linuxContext)->traceMacAddressBuffer))); continue; } if (CsrStrNCmp(argv[i], "-mib=", 5) == 0) { loadMibfile(&argv[i][5], &getMainData(linuxContext)->mibfiles); sme_trace_info((TR_IPC, "sme_schedule_init() : mib file -> %s", argv[i])); continue; } if (CsrStrNCmp(argv[i], "-cal=", 5) == 0) { getMainData(linuxContext)->calibrationDataFile = &argv[i][5]; (void)loadfile(getMainData(linuxContext)->calibrationDataFile, &getMainData(linuxContext)->calibrationData); sme_trace_info((TR_IPC, "sme_schedule_init() : cal file -> %s", getMainData(linuxContext)->calibrationDataFile)); continue; } /* Skip -sme_trace:... as the sme trace module will handle these */ if (CsrStrNCmp(argv[i], "-sme_trace:", 11) == 0) { continue; } if (CsrStrNCmp(argv[i], "-v", CsrStrLen(argv[i])) == 0) { print_versions(); exit(EXIT_CODE_NORMAL_EXIT); } if (CsrStrNCmp(argv[i], "-exitOnError", CsrStrLen(argv[i])) == 0) { getMainData(linuxContext)->exitOnError = TRUE; continue; } if (CsrStrNCmp(argv[i], "-stopOnError", CsrStrLen(argv[i])) == 0) { getMainData(linuxContext)->stopOnError = TRUE; continue; } if (CsrStrNCmp(argv[i], "-h", CsrStrLen(argv[i])) == 0) { print_usage(); exit(EXIT_CODE_WIFION_ERROR); } print_usage(); sme_trace_error((TR_IPC, "error : Unknown commandline option : %s", argv[i])); exit(EXIT_CODE_WIFION_ERROR); } #ifdef IPC_CHARDEVICE if (connectStr) { getMainData(context)->charIpcCon = ipc_chardevice_connect(connectStr, NULL, NULL, NULL, NULL); if (getMainData(context)->charIpcCon == NULL) { sme_trace_crit((TR_IPC, "sme_schedule_init() : char device connect to %s failed", connectStr)); exit(EXIT_CODE_WIFION_ERROR); } } #endif #ifdef IPC_IP getMainData(context)->ipIpcCon = ipc_ip_create((int)ipc_portNumber, NULL, NULL, NULL, NULL); if (getMainData(context)->ipIpcCon == NULL) { sme_trace_crit((TR_IPC, "sme_schedule_init() : ipc_create(port:%d) failed", ipc_portNumber)); exit(EXIT_CODE_WIFION_ERROR); } #ifdef CSR_AMP_ENABLE getMainData(context)->ipHciIpcCon = ipc_ip_create((int)ipc_hciPortNumber, NULL, NULL, NULL, NULL); if (getMainData(context)->ipHciIpcCon == NULL) { sme_trace_crit((TR_IPC, "sme_schedule_init() : ipc_create(port:%d) failed", ipc_hciPortNumber)); exit(EXIT_CODE_WIFION_ERROR); } getMainData(context)->ipAclIpcCon = ipc_ip_create((int)ipc_aclPortNumber, NULL, NULL, NULL, NULL); if (getMainData(context)->ipAclIpcCon == NULL) { sme_trace_crit((TR_IPC, "sme_schedule_init() : ipc_create(port:%d) failed", ipc_aclPortNumber)); exit(EXIT_CODE_WIFION_ERROR); } #endif #endif if (getMainData(linuxContext)->calibrationData.length) { unifi_AppValue appValue; appValue.id = unifi_CalibrationDataValue; appValue.unifi_Value_union.calibrationData = getMainData(linuxContext)->calibrationData; unifi_mgt_claim_sync_access(linuxContext->fsmContext); (void)unifi_mgt_set_value(linuxContext->fsmContext, &appValue); unifi_mgt_release_sync_access(linuxContext->fsmContext); } if (flightmode) { unifi_mgt_wifi_flightmode_req(linuxContext->fsmContext, NULL, &getMainData(context)->address, getMainData(linuxContext)->mibfiles.numElements, getMainData(linuxContext)->mibfiles.dataList); } if (wifion) { /* Set the nextCaldataSaveTime to 1 minute from now */ getMainData(linuxContext)->nextCaldataSaveTime = fsm_get_time_of_day_ms(context->fsmContext) + CALDATA_INITIAL_SAVE_INTERVAL_MS; unifi_mgt_wifi_on_req(linuxContext->fsmContext, NULL, &getMainData(context)->address, getMainData(linuxContext)->mibfiles.numElements, getMainData(linuxContext)->mibfiles.dataList); } }
CsrBool encode_pac_file(FastContext *fastContext) { eapfast_pac_file_format *pac; CsrUint8 *decyphered_pac_data; CsrUint8 digest[CSR_SHA1_DIGEST_LENGTH]; CsrUint8 *scan; CsrUint8 *data_len; CsrUint16 length; CsrInt32 rounded_length; CsrUint8 padding; CsrUint8 key[CSR_SHA1_DIGEST_LENGTH]; CsrUint8 iv[EAPFAST_PAC_CYPHER_IV_LENGTH]; CsrInt32 i; sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "encode_pac_file() :: PAC_key", fastContext->tls.PAC_key, 32)); sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "encode_pac_file() :: PAC_opaque", fastContext->PAC_opaque, fastContext->PAC_opaque_length)); pac = (eapfast_pac_file_format *)CsrPmalloc(CSR_WIFI_SECURITY_MAX_PAC_LENGTH); fastContext->context->setupData.fast_pac = (CsrUint8 *)pac; pac->version = EAPFAST_PAC_FILE_VERSION; pac->defpasswd = 1; /* Using default password */ CsrMemCpy(pac->magicNum, eapfastPacFileMagicLittleEndian, EAPFAST_PAC_FILE_MAGIC_LEN); pac->cypher[0] = 0; /* AES-CBC-128 */ pac->cypher[1] = 1; if ((decyphered_pac_data = CsrPmalloc(MAX_PAC_DATA)) == NULL) { sme_trace_error((TR_SECURITY_LIB, "encode_pac_file() :: memory allocation error.")); return FALSE; } scan = decyphered_pac_data; *scan++ = 0x80; /* Set known values */ *scan++ = 0x0b; data_len = scan; /* Keep pointer to data_len to fill in later */ scan += 2; *scan++ = 0x00; *scan++ = 0x01; /* PAC Key type */ *scan++ = 0x00; *scan++ = 0x20; /* PAC Key length = 32 */ CsrMemCpy(scan, fastContext->tls.PAC_key, 32); scan += 32; *scan++ = 0x00; *scan++ = 0x02; /* PAC Opaque type */ *scan++ = (fastContext->PAC_opaque_length >> 8) & 0xff; *scan++ = fastContext->PAC_opaque_length & 0xff; CsrMemCpy(scan, fastContext->PAC_opaque, fastContext->PAC_opaque_length); scan += fastContext->PAC_opaque_length; length = (CsrUint16)(scan - decyphered_pac_data); *data_len++ = (length >> 8) & 0xff; *data_len++ = length & 0xff; sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "encode_pac_file() :: decyphered_pac_data", decyphered_pac_data, length)); /* Compute the encryption MAC */ CsrCryptoCallSha1(fastContext->context->cryptoContext, NULL, decyphered_pac_data, length, digest); sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "encode_pac_file() :: Encryption MAC", digest, EAPFAST_CHECK_SUM_LEN)); CsrMemCpy(pac->cyphermac, digest, EAPFAST_CHECK_SUM_LEN); sme_trace_info((TR_SECURITY_LIB, "encode_pac_file() :: Decyphered length = %d", length)); /* Need to adjust the length to be a multiple of 128 bits before encoding */ rounded_length = ((length + 16) / 16) * 16; sme_trace_info((TR_SECURITY_LIB, "encode_pac_file() :: Rounded up length = %d", rounded_length)); /* Work out how many padding bytes are required */ padding = (CsrUint8)(rounded_length - length); if (padding == 0) padding = 16; /* Append the padding bytes */ scan = decyphered_pac_data + length; for (i = 0; i < padding; i++) { *scan++ = padding; } length += padding; sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "encode_pac_file() :: Padded decyphered_pac_data", decyphered_pac_data, length)); CsrCryptoCallHmacSha1(fastContext->context->cryptoContext, NULL, pacfile_defPasswd, 17, (CsrUint8 *)"ENC", 3, key); sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "encode_pac_file() :: AES key", key, CSR_SHA1_DIGEST_LENGTH)); /* AES CBC encode the decrypted PAC data */ { CsrUint32 outLength; /* FIXME - the IV should be initialized to a random value */ CsrMemSet(pac->iv, 0, EAPFAST_PAC_CYPHER_IV_LENGTH); /* Make a copy of the IV as the AES encrypt function will not preserve it */ CsrMemCpy(iv, pac->iv, EAPFAST_PAC_CYPHER_IV_LENGTH); CsrCryptoAes128CbcEncrypt(key, iv, decyphered_pac_data, length, pac->blob, &outLength, PAD_MODE_TLS); } /* Adjust to the total length for the integritymac calculation */ length += (sizeof(eapfast_pac_file_format) - 1); /* Zero the MAC before computing */ CsrMemSet(pac->integritymac, 0, EAPFAST_CHECK_SUM_LEN); CsrCryptoCallSha1(fastContext->context->cryptoContext, NULL, fastContext->context->setupData.fast_pac, length, digest); CsrMemCpy(pac->integritymac, digest, EAPFAST_CHECK_SUM_LEN); fastContext->context->setupData.fast_pac_length = length; sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "encode_pac_file() :: PAC", fastContext->context->setupData.fast_pac, length)); return TRUE; }
/*---------------------------------------------------------------------------*/ CsrBool decode_pac_file(FastContext *fastContext, char *password) { CsrUint8 *decyphered_pac_data; CsrUint16 pac_length = 0; eapfast_pac_file_format *pac; CsrUint8 old_mac[EAPFAST_CHECK_SUM_LEN]; CsrUint8 new_mac[CSR_SHA1_DIGEST_LENGTH]; CsrUint16 blob_length; CsrUint8 key[CSR_SHA1_DIGEST_LENGTH]; CsrBool ret_val; sme_trace_info((TR_SECURITY_LIB, "decode_pac_file() :: fast_pac_length = %d", fastContext->context->setupData.fast_pac_length)); if(fastContext->context->setupData.fast_pac_length == 0) { return FALSE; } pac = (eapfast_pac_file_format *)(fastContext->context->setupData.fast_pac); sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "decode_pac_file() :: PAC", fastContext->context->setupData.fast_pac, fastContext->context->setupData.fast_pac_length)); if ((decyphered_pac_data = CsrPmalloc(MAX_PAC_DATA)) == NULL) { sme_trace_error((TR_SECURITY_LIB, "decode_pac_file() :: memory allocation error.")); return FALSE; } pac_length = (CsrUint16)(fastContext->context->setupData.fast_pac_length); /* Sanity check the header. */ if ((pac->version != EAPFAST_PAC_FILE_VERSION) || (pac->cypher[0] != 0) || (pac->cypher[1] != 1) /* accept both endian magic numbers, although Cisco APs seem to put out little endian */ || ( (CsrMemCmp(pac->magicNum, eapfastPacFileMagicLittleEndian, EAPFAST_PAC_FILE_MAGIC_LEN) != 0) && (CsrMemCmp(pac->magicNum, eapfastPacFileMagicBigEndian, EAPFAST_PAC_FILE_MAGIC_LEN) != 0) ) || (pac_length < sizeof(eapfast_pac_file_format) + 8/* Minimum PAC TLV size */) ) { sme_trace_error((TR_SECURITY_LIB, "decode_pac_file() :: Bad PAC file header.")); CsrPfree(decyphered_pac_data); return FALSE; } /* Check the file integrity MAC */ CsrMemCpy(old_mac, pac->integritymac, 16); CsrMemSet(pac->integritymac, 0, 16); CsrCryptoCallSha1(fastContext->context->cryptoContext, NULL, fastContext->context->setupData.fast_pac, pac_length, new_mac); if (CsrMemCmp(old_mac, new_mac, 16) != 0) { sme_trace_error((TR_SECURITY_LIB, "decode_pac_file() :: File Integrity MAC failure.")); CsrPfree(decyphered_pac_data); return FALSE; } /* Calculate the encryption key - HMAC-SHA1(password, "ENC") */ if ((pac->defpasswd) || (password==NULL)) { CsrCryptoCallHmacSha1(fastContext->context->cryptoContext, NULL, pacfile_defPasswd, 17, (CsrUint8 *)"ENC", 3, key); } else { CsrCryptoCallHmacSha1(fastContext->context->cryptoContext, NULL, (CsrUint8 *)password, CsrStrLen(password), (CsrUint8 *)"ENC", 3, key); } sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "decode_pac_file() :: AES key", key, CSR_SHA1_DIGEST_LENGTH)); { CsrUint32 outLength; blob_length = pac_length - (sizeof(eapfast_pac_file_format) - 1); CsrCryptoAes128CbcDecrypt(key, pac->iv, pac->blob, blob_length, decyphered_pac_data, &outLength, PAD_MODE_TLS); } /* Drop the padding bytes from the blob_length as they are not part of the encryption MAC computation*/ blob_length -= (CsrUint16)(decyphered_pac_data[blob_length - 1]); sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "Decrypted blob", decyphered_pac_data, blob_length)); /* Check the encryption MAC */ CsrMemSet(new_mac, 0, CSR_SHA1_DIGEST_LENGTH); CsrCryptoCallSha1(fastContext->context->cryptoContext, NULL, decyphered_pac_data, blob_length, new_mac); #if (EAPFAST_CHECK_SUM_LEN > CSR_SHA1_DIGEST_LENGTH) #error Something gone wrong with the EAP-FAST constants! #endif if (CsrMemCmp(pac->cyphermac, new_mac, EAPFAST_CHECK_SUM_LEN) != 0) { sme_trace_error((TR_SECURITY_LIB, "decode_pac_file() :: Encryption MAC failure.")); sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "Supplied MAC", pac->cyphermac, EAPFAST_CHECK_SUM_LEN)); sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "Computed MAC", new_mac, EAPFAST_CHECK_SUM_LEN)); CsrPfree(decyphered_pac_data); return FALSE; } /* decyphered_pac_data should now contain a complete PAC TLV */ ret_val = parse_PAC_TLV(fastContext, decyphered_pac_data, blob_length); CsrPfree(decyphered_pac_data); return ret_val; }