/* PBC Overlapped detection */ int wps_pb_check_pushtime(unsigned long time) { int i; int PBC_sta = PBC_OVERLAP_CNT; for (i = 0; i < PBC_OVERLAP_CNT; i++) { /* * 120 seconds is too sensitive, it have a chance that we receive * a last ProbeReq with WPS_DEVICEPWDID_PUSH_BTN after clearing * this station. So plus 2 seconds */ if ((time < pbc_info[i].last_time) || ((time - pbc_info[i].last_time) > (120 + 2))) { memset(&pbc_info[i], 0, sizeof(PBC_STA_INFO)); } if (pbc_info[i].last_time == 0) PBC_sta--; } TUTRACE((TUTRACE_INFO, "There are %d sta in PBC mode!\n", PBC_sta)); TUTRACE((TUTRACE_INFO, "sta1: %02x:%02x:%02x:%02x:%02x:%02x, LT:%d/CT:%d\n", pbc_info[0].mac[0], pbc_info[0].mac[1], pbc_info[0].mac[2], pbc_info[0].mac[3], pbc_info[0].mac[4], pbc_info[0].mac[5], pbc_info[0].last_time, time)); TUTRACE((TUTRACE_INFO, "sta2: %02x:%02x:%02x:%02x:%02x:%02x, LT:%d/CT:%d\n", pbc_info[1].mac[0], pbc_info[1].mac[1], pbc_info[1].mac[2], pbc_info[1].mac[3], pbc_info[1].mac[4], pbc_info[1].mac[5], pbc_info[1].last_time, time)); return PBC_sta; }
static uint32 wps_sendMsg(void *mcdev, TRANSPORT_TYPE trType, char * dataBuffer, uint32 dataLen) { uint32 retVal = WPS_SUCCESS; TUTRACE((TUTRACE_INFO, "In wps_sendMsg\n")); if (trType < 1 || trType >= TRANSPORT_TYPE_MAX) { TUTRACE((TUTRACE_ERR, "Transport Type is not within the " "accepted range\n")); return WPS_ERR_INVALID_PARAMETERS; } switch (trType) { case TRANSPORT_TYPE_EAP: retVal = ap_eap_sm_sendMsg(dataBuffer, dataLen); break; #ifdef WPS_UPNP_DEVICE case TRANSPORT_TYPE_UPNP_DEV: retVal = ap_upnp_sm_sendMsg(dataBuffer, dataLen); break; #endif /* WPS_UPNP_DEVICE */ default: break; } if (retVal != WPS_SUCCESS) { TUTRACE((TUTRACE_ERR, "WriteData for " "trType %d failed.\n", trType)); } return retVal; }
void reg_proto_encrypt_data(BufferObj *plainText, BufferObj *encrKey, BufferObj *authKey, BufferObj *cipherText, BufferObj *iv) { BufferObj *buf = buffobj_new(); uint8 ivBuf[SIZE_128_BITS]; /* 10 rounds for cbc 128 = (10+1) * 4 uint32 */ uint32 rk[44]; uint8 outBuf[1024]; int encrypt_len; if (!buf) return; if (plainText->m_dataLength == 0) { TUTRACE((TUTRACE_ERR, "Invalid parameters \n")); buffobj_del(buf); return; } /* Generate a random iv */ RAND_bytes(ivBuf, SIZE_128_BITS); buffobj_Reset(iv); buffobj_Append(iv, SIZE_128_BITS, ivBuf); /* Now encrypt the plaintext and mac using the encryption key and IV. */ buffobj_Append(buf, plainText->m_dataLength, plainText->pBase); TUTRACE((TUTRACE_ERR, "RPROTO: calling encryption of %d bytes\n", buf->m_dataLength)); rijndaelKeySetupEnc(rk, encrKey->pBase, 128); encrypt_len = aes_cbc_encrypt_pad(rk, 16, ivBuf, buf->m_dataLength, plainText->pBase, outBuf, PAD_LEN_PADDING); buffobj_Append(cipherText, encrypt_len, outBuf); buffobj_del(buf); }
int wps_osl_init(char *bssid) { int eap_fd = wps_eap_get_handle(); int ret; struct ifreq ifr; if (!if_name[0]) { TUTRACE((TUTRACE_ERR, "Wireless Interface not specified.\n")); return WPS_ERR_SYSTEM; } /* Check interface address */ memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name)); if ((ret = ioctl(eap_fd, SIOCGIFHWADDR, &ifr)) < 0) { TUTRACE((TUTRACE_ERR, "Get interface mac failed\n")); return WPS_ERR_SYSTEM; } /* Copy the result back */ memcpy(my_mac, ifr.ifr_hwaddr.sa_data, 6); TUTRACE((TUTRACE_INFO, "set my_mac %02x:%02x:%02x:%02x:%02x:%02x\n", my_mac[0], my_mac[1], my_mac[2], my_mac[3], my_mac[4], my_mac[5])); /* record destination bssid */ if (bssid) { memcpy(peer_mac, bssid, 6); TUTRACE((TUTRACE_INFO, "set peer_mac %02x:%02x:%02x:%02x:%02x:%02x\n", peer_mac[0], peer_mac[1], peer_mac[2], peer_mac[3], peer_mac[4], peer_mac[5])); } return WPS_SUCCESS; }
void reg_proto_derivekey(BufferObj *KDK, BufferObj *prsnlString, uint32 keyBits, BufferObj *key) { uint32 i = 0, iterations = 0; BufferObj *input, *output; uint8 hmac[SIZE_256_BITS]; uint32 hmacLen = 0; uint8 *inPtr; uint32 temp; input = buffobj_new(); if (!input) return; output = buffobj_new(); if (!output) { buffobj_del(input); return; } TUTRACE((TUTRACE_INFO, "RPROTO: Deriving a key of %d bits\n", keyBits)); iterations = ((keyBits/8) + PRF_DIGEST_SIZE - 1)/PRF_DIGEST_SIZE; /* * Prepare the input buffer. During the iterations, we need only replace the * value of i at the start of the buffer. */ temp = WpsHtonl(i); buffobj_Append(input, SIZE_4_BYTES, (uint8 *)&temp); buffobj_Append(input, prsnlString->m_dataLength, prsnlString->pBase); temp = WpsHtonl(keyBits); buffobj_Append(input, SIZE_4_BYTES, (uint8 *)&temp); inPtr = input->pBase; for (i = 0; i < iterations; i++) { /* Set the current value of i at the start of the input buffer */ *(uint32 *)inPtr = WpsHtonl(i+1) ; /* i should start at 1 */ hmac_sha256(KDK->pBase, SIZE_256_BITS, input->pBase, input->m_dataLength, hmac, &hmacLen); buffobj_Append(output, hmacLen, hmac); } /* Sanity check */ if (keyBits/8 > output->m_dataLength) { TUTRACE((TUTRACE_ERR, "RPROTO: Key derivation generated less bits " "than asked\n")); buffobj_del(output); buffobj_del(input); return; } /* * We now have at least the number of key bits requested. * Return only the number of bits asked for. Discard the excess. */ buffobj_Append(key, keyBits/8, output->pBase); buffobj_del(output); buffobj_del(input); TUTRACE((TUTRACE_INFO, "RPROTO: End Deriving a key of %d bits\n", keyBits)); }
uint32 wps_enrUpnpGetDeviceInfoCheck(EnrSM *e, void *inbuffer, uint32 in_len, void *outbuffer, uint32 *out_len) { if (!inbuffer || !in_len) { if (false == e->reg_info->initialized) { TUTRACE((TUTRACE_ERR, "ENRSM: Not yet initialized.\n")); return WPS_ERR_NOT_INITIALIZED; } if (START != e->reg_info->e_smState) { TUTRACE((TUTRACE_INFO, "\n======e_lastMsgSent != M1, " "Step GetDeviceInfo=%d ======\n", wps_getUpnpDevGetDeviceInfo(e->g_mc))); if (wps_getUpnpDevGetDeviceInfo(e->g_mc)) { wps_setUpnpDevGetDeviceInfo(e->g_mc, false); /* copy to msg_to_send buffer */ if (*out_len < e->reg_info->outMsg->m_dataLength) { e->reg_info->e_smState = FAILURE; TUTRACE((TUTRACE_ERR, "output message buffer to small\n")); return WPS_MESSAGE_PROCESSING_ERROR; } memcpy(outbuffer, (char *)e->reg_info->outMsg->pBase, e->reg_info->outMsg->m_dataLength); *out_len = e->reg_info->outMsg->m_dataLength; return WPS_SEND_MSG_CONT; } return WPS_SUCCESS; } } return WPS_CONT; }
int ap_eap_sm_startWPSReg(unsigned char *sta_mac, unsigned char *ap_mac) { unsigned char *mac; int retVal; mac = lookupSta(sta_mac, SEARCH_ENTER); if (!mac) { TUTRACE((TUTRACE_ERR, "no sta...\n")); return -1; } TUTRACE((TUTRACE_ERR, "Build WPS Start!\n")); /* reset counter */ apEapState->eap_id = 1; /* store whcih if sta come from */ memcpy(&apEapState->bssid, ap_mac, ETHER_ADDR_LEN); /* Request Start message */ retVal = ap_eap_sm_req_start(); return retVal; }
uint32 ap_eap_sm_init(void *mc_dev, char *mac_sta, char * (*parse_msg)(char *, int, int *), unsigned int (*send_data)(char *, uint32), int eap_frag_threshold) { TUTRACE((TUTRACE_INFO, "Initial...\n")); memset(&s_apEapState, 0, sizeof(EAP_WPS_AP_STATE)); apEapState = &s_apEapState; apEapState->mc_dev = mc_dev; memcpy(apEapState->sta_mac, mac_sta, ETHER_ADDR_LEN); if (parse_msg) apEapState->parse_msg = parse_msg; if (send_data) apEapState->send_data = send_data; /* For fragmentation */ apEapState->next_frag_to_send = apEapState->msg_to_send; /* WSC 2.0 */ apEap_wps_version2 = wps_get_version2(mc_dev); apEapState->eap_frag_threshold = EAP_WPS_FRAG_MAX; if (eap_frag_threshold >= 100 && eap_frag_threshold < EAP_WPS_FRAG_MAX) apEapState->eap_frag_threshold = eap_frag_threshold; TUTRACE((TUTRACE_INFO, "ap_eap_sm_init: EAP Frag Threshold %d\n", apEapState->eap_frag_threshold)); return WPS_SUCCESS; }
/* Send EAP fragment ACK */ static int ap_eap_sm_sendFACK() { WpsEapHdr wpsEapHdr; /* check sta status */ if (!WPS_STA_ACTIVE()) { TUTRACE((TUTRACE_ERR, "sta not in use!\n")); return WPS_ERROR_MSG_TIMEOUT; } TUTRACE((TUTRACE_INFO, "Build EAP fragment ACK\n")); wpsEapHdr.code = EAP_CODE_REQUEST; wpsEapHdr.id = apEapState->eap_id; wpsEapHdr.length = WpsHtons(sizeof(WpsEapHdr)); wpsEapHdr.type = EAP_TYPE_WPS; wpsEapHdr.vendorId[0] = WPS_VENDORID1; wpsEapHdr.vendorId[1] = WPS_VENDORID2; wpsEapHdr.vendorId[2] = WPS_VENDORID3; wpsEapHdr.vendorType = WpsHtonl(WPS_VENDORTYPE); wpsEapHdr.opcode = WPS_FRAG_ACK; wpsEapHdr.flags = 0; ap_eap_sm_sendEapol(apEapState->msg_to_send, (char *)&wpsEapHdr, sizeof(WpsEapHdr)); return WPS_SUCCESS; }
uint32 ap_eap_sm_sendMsg(char *dataBuffer, uint32 dataLen) { uint32 retVal; eapol_header_t *eapolHdr = (eapol_header_t *)apEapState->msg_to_send; WpsEapHdr *wpsEapHdr; TUTRACE((TUTRACE_INFO, "In ap_eap_sm_sendMsg buffer Length = %d\n", dataLen)); retVal = ap_eap_sm_create_pkt(dataBuffer, dataLen, EAP_CODE_REQUEST); if (retVal == WPS_SUCCESS) { /* Shift EAP_WPS_LF_OFFSET */ if (dataLen < apEapState->eap_frag_threshold) eapolHdr = (eapol_header_t *)&apEapState->msg_to_send[EAP_WPS_LF_OFFSET]; wpsEapHdr = (WpsEapHdr *)eapolHdr->body; ap_eap_sm_sendEap((char *)wpsEapHdr, WpsNtohs((uint8*)&wpsEapHdr->length)); apEapState->state = PROCESSING_PROTOCOL; } else { TUTRACE((TUTRACE_ERR, "Send EAP FAILURE to station!\n")); ap_eap_sm_Failure(apEap_wps_version2 ? 1 : 0); retVal = TREAP_ERR_SENDRECV; } return retVal; }
bool CRegProtocol::ValidateMac(BufferObj &data, uint8 *hmac, BufferObj &key) { uint8 dataMac[BUF_SIZE_256_BITS]; //First calculate the hmac of the data if(HMAC(EVP_sha256(), key.GetBuf(), SIZE_256_BITS, data.GetBuf(), data.Length(), dataMac, NULL) == NULL) { TUTRACE((TUTRACE_ERR, "RPROTO: HMAC failed\n")); if (TUTRACELEVEL & TUVERBOSE && g_verbose) { // for debugging purposes printf("Computed HMAC (note: only first 64 bits will be compared)\n"); for (int i = 0; i < BUF_SIZE_256_BITS; i++) { printf("%2x ",dataMac[i]); } printf("\nHMAC from Authenticator(should match first 64 bits of computed HMAC)\n"); for (int i = 0; i < 8; i++) { printf("%2x ",hmac[i]); } printf("\nKey is:\n"); for (int i = 0; i < 8; i++) { printf("%2x ",(key.GetBuf())[i]); } printf("\n"); } throw RPROT_ERR_CRYPTO; } else { if (TUTRACELEVEL & TUVERBOSE && g_verbose) { // for debugging purposes printf("Computed HMAC (note: only first 64 bits will be compared)\n"); for (int i = 0; i < BUF_SIZE_256_BITS; i++) { printf("%2x ",dataMac[i]); } printf("\nHMAC from Authenticator(should match first 64 bits of computed HMAC)\n"); for (int i = 0; i < 8; i++) { printf("%2x ",hmac[i]); } printf("\nKey is:\n"); for (int i = 0; i < BUF_SIZE_256_BITS; i++) { printf("%2x ",(key.GetBuf())[i]); } printf("\n"); } } //next, compare it against the received hmac TUTRACE((TUTRACE_INFO, "RPROTO: Verifying the first 64 bits of the generated HMAC\n")); if(memcmp(dataMac, hmac, SIZE_64_BITS) != 0) { printf("RPROTO: HMAC results don't match\n"); return false; } TUTRACE((TUTRACE_VERBOSE, "RPROTO: HMAC results match\n")); return true; }
/* * Receive a fragmentation then send EAP_FRAG_ACK. */ static int ap_eap_sm_process_frag(char *eap_msg) { int ret; int LF_bytes = 0; WpsEapHdr *wpsEapHdr = (WpsEapHdr *)eap_msg; uint32 wps_len = WpsNtohs((uint8*)&wpsEapHdr->length) - sizeof(WpsEapHdr); int wps_data_received = apEapState->total_received - sizeof(WpsEapHdr); TUTRACE((TUTRACE_INFO, "Receive a EAP WPS fragment packet\n")); /* Total length checking */ if (apEapState->total_bytes_to_recv < wps_data_received + wps_len) { TUTRACE((TUTRACE_ERR, "Received WPS data len %d excess total bytes to " "receive %d\n", wps_data_received + wps_len, apEapState->total_bytes_to_recv)); return EAP_FAILURE; } /* Copy to frags_received */ /* First fragmentation include WpsEapHdr without length field */ if (apEapState->total_received == 0) { memcpy(apEapState->frags_received, eap_msg, sizeof(WpsEapHdr)); apEapState->total_received += sizeof(WpsEapHdr); /* Ignore length field 2 bytes copy */ LF_bytes = EAP_WPS_LF_OFFSET; } /* WPS data */ memcpy(&apEapState->frags_received[apEapState->total_received], eap_msg + sizeof(WpsEapHdr) + LF_bytes, wps_len - LF_bytes); apEapState->total_received += wps_len - LF_bytes; /* Is last framentation? */ if (wpsEapHdr->flags & EAP_WPS_FLAGS_MF) { /* Increase eap_id */ apEapState->eap_id++; /* Send WPS_FRAG_ACK */ ret = ap_eap_sm_sendFACK(); if (ret == WPS_SUCCESS) return WPS_CONT; return ret; } /* Got all fragmentations, adjust WpsEapHdr */ wpsEapHdr = (WpsEapHdr *)apEapState->frags_received; wpsEapHdr->length = WpsHtons((uint16)apEapState->total_received); TUTRACE((TUTRACE_ERR, "Received all WPS fragmentations, total bytes of WPS data " "to receive %d, received %d\n", apEapState->total_bytes_to_recv, apEapState->total_received - sizeof(WpsEapHdr))); return WPS_SUCCESS; }
static void wpssta_print_credential(WpsEnrCred *credential, char *title) { char keystr[65]; if (title) TUTRACE((TUTRACE_INFO, "\n%s\n", title)); TUTRACE((TUTRACE_INFO, "SSID = %s\n", credential->ssid)); TUTRACE((TUTRACE_INFO, "Key Mgmt type is %s\n", credential->keyMgmt)); strncpy(keystr, credential->nwKey, credential->nwKeyLen); keystr[credential->nwKeyLen] = 0; TUTRACE((TUTRACE_INFO, "Key : %s\n", keystr)); if (credential->encrType == 0) { TUTRACE((TUTRACE_INFO, "Encryption : NONE\n")); } else { if (credential->encrType & ENCRYPT_WEP) { TUTRACE((TUTRACE_INFO, "Encryption : WEP\n")); TUTRACE((TUTRACE_INFO, "WEP Index: %d\n", credential->wepIndex)); } if (credential->encrType & ENCRYPT_TKIP) TUTRACE((TUTRACE_INFO, "Encryption : TKIP\n")); if (credential->encrType & ENCRYPT_AES) TUTRACE((TUTRACE_INFO, "Encryption : AES\n")); } }
uint32 CRegProtocol::CreatePrivateKey(char *name, EVP_PKEY **key) { TU_RET err = TU_ERROR_CRYPTO_FAILED; RSA *rsaKey; EVP_PKEY *pkey; FILE *fp; rsaKey = RSA_generate_key(1024, 65537, NULL, NULL); if(rsaKey == NULL) { TUTRACE((TUTRACE_ERR, "Couldn't generate RSA key\n")); goto EXIT; } //Now store it in a PKEY pkey = EVP_PKEY_new(); if(!pkey) { TUTRACE((TUTRACE_ERR, "Couldn't generate new EVP key\n")); goto EXIT; } if(!EVP_PKEY_assign_RSA(pkey, rsaKey)) { TUTRACE((TUTRACE_ERR, "Couldn't assign RSA key to EVP key\n")); RSA_free(rsaKey); goto EXIT; } fp = fopen(name, "w"); if(!PEM_write_PKCS8PrivateKey(fp, pkey, NULL, NULL, 0, NULL, NULL)) { TUTRACE((TUTRACE_ERR, "Error writing Signing key to file\n")); fclose(fp); goto ERR_EVP; } fclose(fp); if(key) *key = pkey; else EVP_PKEY_free(pkey); return TU_SUCCESS; ERR_EVP: EVP_PKEY_free(pkey); EXIT: return err; }
static int wpssta_success(wpssta_wksp_t *sta_wksp) { int retVal = WPS_RESULT_SUCCESS, ssidlen = 0; char ssid[SIZE_SSID_LENGTH]; WpsEnrCred *credential = (WpsEnrCred *)malloc(sizeof(WpsEnrCred)); /* Remove WPS IE before doing 4-way handshake */ rem_wps_ie(NULL, 0, VNDR_IE_PRBREQ_FLAG); if (b_wps_version2) rem_wps_ie(NULL, 0, VNDR_IE_ASSOCREQ_FLAG); if (credential == NULL) { TUTRACE((TUTRACE_INFO, "memory allocate failed!!\n")); wpsenr_osl_proc_states(WPS_MSG_ERR); /* FAILED */ return WPS_RESULT_FAILURE; } TUTRACE((TUTRACE_INFO, "WPS Protocol SUCCEEDED !!\n")); /* get credentials */ if (sta_wksp->mode == WPSM_STA_BUILTINREG) { if (sta_wksp->configap == true) wps_get_reg_M8credentials(credential); else wps_get_reg_M7credentials(credential); } else { wps_get_ssid(ssid, &ssidlen); wps_get_credentials(credential, ssid, ssidlen); } wpssta_print_credential(credential, "Current AP Credential"); wpsenr_osl_proc_states(WPS_OK); /* SUCCEEDED */ if (wpsenr_osl_set_wsec(sta_wksp->ess_id, credential, (sta_wksp->mode == WPSM_STA_BUILTINREG) ? EModeRegistrar : EModeClient)) retVal = WPS_RESULT_SUCCESS_RESTART; else retVal = WPS_RESULT_SUCCESS; /* free memory */ free(credential); /* WPS 2.0. test 5.1.1, leave network before do_wpa_psk with new security */ WpsSleepMs(500); leave_network(); return retVal; }
uint32 reg_proto_generate_dhkeypair(DH **DHKeyPair, BufferObj *pubKey) { uint8 temp[SIZE_PUB_KEY]; uint32 g = 0; /* 1. Initialize the DH structure */ *DHKeyPair = DH_new(); if (*DHKeyPair == NULL) { TUTRACE((TUTRACE_ERR, "RPROTO: DH_new failed\n")); return RPROT_ERR_CRYPTO; } (*DHKeyPair)->p = BN_new(); if ((*DHKeyPair)->p == NULL) { TUTRACE((TUTRACE_ERR, "RPROTO: BN_new p failed\n")); return RPROT_ERR_CRYPTO; } (*DHKeyPair)->g = BN_new(); if ((*DHKeyPair)->g == NULL) { TUTRACE((TUTRACE_ERR, "RPROTO: BN_new g failed\n")); return RPROT_ERR_CRYPTO; } /* 2. load the value of P */ if (BN_bin2bn(DH_P_VALUE, BUF_SIZE_1536_BITS, (*DHKeyPair)->p) == NULL) { TUTRACE((TUTRACE_ERR, "RPROTO: load value p failed\n")); return RPROT_ERR_CRYPTO; } /* 3. load the value of G */ g = WpsHtonl(DH_G_VALUE); if (BN_bin2bn((uint8 *)&g, 4, (*DHKeyPair)->g) == NULL) { TUTRACE((TUTRACE_ERR, "RPROTO: load value g failed\n")); return RPROT_ERR_CRYPTO; } /* 4. generate the DH key */ if (WPS_DH_GENERATE_KEY(NULL, *DHKeyPair) == 0) { TUTRACE((TUTRACE_ERR, "RPROTO: DH generate key failed\n")); return RPROT_ERR_CRYPTO; } /* 5. extract the DH public key */ if (reg_proto_BN_bn2bin((*DHKeyPair)->pub_key, temp) != SIZE_PUB_KEY) { TUTRACE((TUTRACE_ERR, "RPROTO: invalid public key length\n")); return RPROT_ERR_CRYPTO; } TUTRACE((TUTRACE_ERR, "DH generate 6\n")); buffobj_Append(pubKey, SIZE_PUB_KEY, temp); TUTRACE((TUTRACE_ERR, "DH generate 7\n")); return WPS_SUCCESS; }
void * wps_init(void *bcmwps, DevInfo *ap_devinfo) { WPSAPI_T *gp_mc; DevInfo *dev_info; gp_mc = (WPSAPI_T *)alloc_init(sizeof(*gp_mc)); if (!gp_mc) { TUTRACE((TUTRACE_INFO, "wps_init::malloc failed!\n")); return 0; } gp_mc->dev_info = devinfo_new(); if (gp_mc->dev_info == NULL) goto error; /* copy user provided DevInfo to mp_deviceInfo */ dev_info = gp_mc->dev_info; memcpy(dev_info, ap_devinfo, sizeof(DevInfo)); /* copy prebuild enrollee noce and private key */ if (dev_info->flags & DEVINFO_FLAG_PRE_PRIV_KEY) { if (reg_proto_generate_prebuild_dhkeypair( &dev_info->DHSecret, dev_info->pre_privkey) != WPS_SUCCESS) { TUTRACE((TUTRACE_ERR, "wps_init::prebuild_dhkeypair failed!\n")); goto error; } } else { if (reg_proto_generate_dhkeypair(&dev_info->DHSecret) != WPS_SUCCESS) { TUTRACE((TUTRACE_ERR, "wps_init::gen dhkeypair failed!\n")); goto error; } } gp_mc->mb_initialized = true; TUTRACE((TUTRACE_INFO, "wps_init::Done!\n")); /* Everything's initialized ok */ gp_mc->bcmwps = bcmwps; return (void *)gp_mc; error: TUTRACE((TUTRACE_ERR, "wps_init::Init failed\n")); if (gp_mc) { wps_deinit(gp_mc); } return 0; }
void CRegProtocol::DeriveKey(BufferObj &KDK, BufferObj &prsnlString, uint32 keyBits, BufferObj &key) { uint32 i = 0, iterations = 0; BufferObj input, output; uint8 hmac[SIZE_256_BITS]; uint32 hmacLen = 0; uint8 *inPtr; uint32 temp; TUTRACE((TUTRACE_INFO, "RPROTO: Deriving a key of %d bits\n", keyBits)); iterations = ((keyBits/8) + PRF_DIGEST_SIZE - 1)/PRF_DIGEST_SIZE; //Prepare the input buffer. During the iterations, we need only replace the //value of i at the start of the buffer. temp = WscHtonl(i); input.Append(SIZE_4_BYTES, (uint8 *)&temp); input.Append(prsnlString.Length(), prsnlString.GetBuf()); temp = WscHtonl(keyBits); input.Append(SIZE_4_BYTES, (uint8 *)&temp); inPtr = input.GetBuf(); for(i = 0; i < iterations; i++) { //Set the current value of i at the start of the input buffer *(uint32 *)inPtr = WscHtonl(i+1); //i should start at 1 if(HMAC(EVP_sha256(), KDK.GetBuf(), SIZE_256_BITS, input.GetBuf(), input.Length(), hmac, &hmacLen) == NULL) { TUTRACE((TUTRACE_ERR, "RPROTO: HMAC failed\n")); throw RPROT_ERR_CRYPTO; } output.Append(hmacLen, hmac); } //Sanity check if(keyBits/8 > output.Length()) { TUTRACE((TUTRACE_ERR, "RPROTO: Key derivation generated less bits " "than asked\n")); throw RPROT_ERR_CRYPTO; } //We now have at least the number of key bits requested. //Return only the number of bits asked for. Discard the excess. key.Append(keyBits/8, output.GetBuf()); }
/* * Search for or create a STA. * We can only handle only ONE station at a time. * If `enter' is not set, do not create it when one is not found. */ static unsigned char* lookupSta(unsigned char *sta_mac, sta_lookup_mode_t mode) { unsigned char *mac = NULL; int sta_active = WPS_STA_ACTIVE(); /* Search if the entry in on the list */ if (sta_active && (!memcmp(&apEapState->sta_mac, sta_mac, ETHER_ADDR_LEN))) { mac = apEapState->sta_mac; } /* create a new entry if necessary */ if (!mac && mode == SEARCH_ENTER) { if (!sta_active) { /* Initialize entry */ memcpy(&apEapState->sta_mac, sta_mac, ETHER_ADDR_LEN); /* Initial STA state: */ apEapState->state = INIT; apEapState->eap_id = 0; mac = apEapState->sta_mac; } else TUTRACE((TUTRACE_ERR, "Sta in use\n")); } return mac; }
uint32 ap_eap_sm_sendWPSStart() { WpsEapHdr wpsEapHdr; /* check sta status */ if (!WPS_STA_ACTIVE()) { TUTRACE((TUTRACE_ERR, "sta not in use!\n")); return WPS_ERROR_MSG_TIMEOUT; } wpsEapHdr.code = EAP_CODE_REQUEST; wpsEapHdr.id = apEapState->eap_id; wpsEapHdr.length = WpsHtons(sizeof(WpsEapHdr)); wpsEapHdr.type = EAP_TYPE_WPS; wpsEapHdr.vendorId[0] = WPS_VENDORID1; wpsEapHdr.vendorId[1] = WPS_VENDORID2; wpsEapHdr.vendorId[2] = WPS_VENDORID3; wpsEapHdr.vendorType = WpsHtonl(WPS_VENDORTYPE); wpsEapHdr.opcode = WPS_Start; wpsEapHdr.flags = 0; ap_eap_sm_sendEapol(apEapState->msg_to_send, (char *)&wpsEapHdr, sizeof(WpsEapHdr)); apEapState->state = EAP_START_SEND; apEapState->sent_msg_id = WPS_PRIVATE_ID_WPS_START; return WPS_SUCCESS; }
devcfg * devcfg_new() { devcfg *inf = (devcfg*)alloc_init(sizeof(devcfg)); if (!inf) return NULL; inf->mp_deviceInfo = (DevInfo *)alloc_init(sizeof(DevInfo)); if (!inf->mp_deviceInfo) { TUTRACE((TUTRACE_INFO, "Info::Info: Could not create deviceInfo\n")); free(inf); return NULL; } /* Initialize other member variables */ memset(inf->mp_deviceInfo, 0, sizeof(DevInfo)); inf->mp_deviceInfo->assocState = WPS_ASSOC_NOT_ASSOCIATED; inf->mp_deviceInfo->configError = 0; /* No error */ inf->mp_deviceInfo->devPwdId = WPS_DEVICEPWDID_DEFAULT; inf->mb_infoConfigSet = false; inf->mb_useUsbKey = false; inf->mb_regWireless = false; inf->mb_useUpnp = false; inf->mb_nwKeySet = false; inf->m_nwKeyLen = 0; inf->mp_dhKeyPair = NULL; inf->mcp_devPwd = NULL; memset(inf->m_pubKey, 0, SIZE_PUB_KEY); memset(inf->m_sha256Hash, 0, SIZE_256_BITS); return inf; }
/* Add for PF3 */ static uint32 wps_regUpnpERFilter(RegSM *r, BufferObj *msg, uint32 msgType) { uint32 err; /* * If AP have received M2 form one External Registrar, * AP must ignore forwarding messages from other * External Registrars. */ if (r->m_er_sentM2 == false) { if (msgType == WPS_ID_MESSAGE_M2) { /* Save R-Nonce */ err = reg_proto_get_nonce(r->m_er_nonce, msg, WPS_ID_REGISTRAR_NONCE); if (err != WPS_SUCCESS) { TUTRACE((TUTRACE_ERR, "ENRSM: Get R-Nonce error: %d\n", err)); } else { r->m_er_sentM2 = true; } } } else { /* Filter UPnP to EAP messages by R-Nonce */ err = reg_proto_check_nonce(r->m_er_nonce, msg, WPS_ID_REGISTRAR_NONCE); if (err == RPROT_ERR_NONCE_MISMATCH) return WPS_CONT; } return WPS_SUCCESS; }
int wps_upnpDevSSR(WPSAPI_T *g_mc, CTlvSsrIE *ssrmsg) { WPS_SCMODE sc_mode = g_mc->dev_info->sc_mode; uint8 scState = g_mc->dev_info->scState; TUTRACE((TUTRACE_INFO, "MC_Recd CB_TRUPNP_DEV_SSR\n")); /* * Added to support SetSelectedRegistrar * If we are an AP+Proxy, then add the SelectedRegistrar TLV * to the WPS IE in the Beacon * This call will fail if the right WLAN drivers are not used. */ if (sc_mode == SCMODE_AP_REGISTRAR) { wps_setWpsIE(g_mc, scState, ssrmsg->selReg.m_data, ssrmsg->devPwdId.m_data, ssrmsg->selRegCfgMethods.m_data, ssrmsg->authorizedMacs.m_data, ssrmsg->authorizedMacs.subtlvbase.m_len); } return WPS_CONT; }
/* Get first non-WPS V2 registrar's ipaddr when no uuid_r and enroll_mac arguments */ char * ap_ssr_get_ipaddr(char* uuid_r, char *enroll_mac) { void *findobj; int findtype; WPS_SSR_SCB *scb; if (!uuid_r && !enroll_mac) { findobj = NULL; findtype = WPS_SSR_SCB_FIND_ANY; } else { if (uuid_r) { findobj = uuid_r; findtype = WPS_SSR_SCB_FIND_UUID_R; } else { findobj = enroll_mac; findtype = WPS_SSR_SCB_FIND_AUTHORIED_MAC; } } /* Find scb by findobj */ scb = ap_ssr_find_scb(findobj, findtype, WPS_SSR_SCB_SEARCH_ONLY); if (scb == NULL) { TUTRACE((TUTRACE_INFO, "Can not find scb\n")); return empty_ipaddr; } return scb->ipaddr; }
int ap_eap_sm_process_timeout() { /* If there is a message pending, re-send for a limited number of time. */ if (apEapState->last_sent_len == 0) { TUTRACE((TUTRACE_ERR, "No data avaliable to retransmit.\n")); return EAP_TIMEOUT; } if (apEapState->resent_count <= EAP_MAX_RESEND_COUNT) { ap_eap_sm_resend_last_sent(); TUTRACE((TUTRACE_ERR, "timeout receiving from STA. Retry previous message\n")); return WPS_CONT; } else { TUTRACE((TUTRACE_ERR, "Retry count exceeded. Bail out\n")); return EAP_TIMEOUT; } }
bool reg_proto_validate_mac(BufferObj *data, uint8 *hmac, BufferObj *key) { uint8 dataMac[BUF_SIZE_256_BITS]; /* First calculate the hmac of the data */ hmac_sha256(key->pBase, SIZE_256_BITS, data->pBase, data->m_dataLength, dataMac, NULL); /* next, compare it against the received hmac */ TUTRACE((TUTRACE_INFO, "RPROTO: Verifying the first 64 bits of the generated HMAC\n")); if (memcmp(dataMac, hmac, SIZE_64_BITS) != 0) { TUTRACE((TUTRACE_ERR, "RPROTO: HMAC results don't match\n")); return false; } return true; }
static void wpssta_filter_credential(WpsEnrCred *credential) { int encrType_mixed = (ENCRYPT_TKIP | ENCRYPT_AES); /* Always use WPA2PSK when both WPAPSK and WPA2PSK enabled */ if (strstr(credential->keyMgmt, "WPA-PSK") && strstr(credential->keyMgmt, "WPA2-PSK")) { strcpy(credential->keyMgmt, "WPA2-PSK"); TUTRACE((TUTRACE_INFO, "Key Mgmt type is mixed-mode, pick WPA2-PSK up\n")); } /* Always use AES when encryptoin type in mixed-mode */ if ((credential->encrType & encrType_mixed) == encrType_mixed) { credential->encrType &= ~ENCRYPT_TKIP; TUTRACE((TUTRACE_INFO, "Encryption is mixed-mode, pick AES up\n")); } }
void reg_proto_generate_sha256hash(BufferObj *inBuf, BufferObj *outBuf) { uint8 Hash[SIZE_256_BITS]; if (SHA256(inBuf->pBase, inBuf->m_dataLength, Hash) == NULL) { TUTRACE((TUTRACE_ERR, "RPROTO: SHA256 calculation failed\n")); return; } buffobj_Append(outBuf, SIZE_256_BITS, Hash); }
uint32 reg_proto_check_nonce(IN uint8 *nonce, IN BufferObj *msg, IN int nonceType) { uint16 type; if ((nonceType != WPS_ID_REGISTRAR_NONCE) && (nonceType != WPS_ID_ENROLLEE_NONCE)) { TUTRACE((TUTRACE_ERR, "RPROTO: Invalid attribute ID passed to" " CheckNonce\n")); return WPS_ERR_INVALID_PARAMETERS; } while (1) { type = buffobj_NextType(msg); if (!type) break; if (nonceType == type) { if (!(memcmp(nonce, msg->pCurrent+sizeof(WpsTlvHdr), SIZE_128_BITS))) { buffobj_Rewind(msg); return WPS_SUCCESS; } else { TUTRACE((TUTRACE_ERR, "RPROTO: Nonce mismatch\n")); buffobj_Rewind(msg); return RPROT_ERR_NONCE_MISMATCH; } } /* * advance past the TLV - the total number of bytes to advance is * the size of the TLV header + the length indicated in the header */ if (!(buffobj_Advance(msg, sizeof(WpsTlvHdr) + WpsNtohs((msg->pCurrent+sizeof(uint16)))))) { TUTRACE((TUTRACE_ERR, "RPROTO: Didn't find nonce\n")); break; } } buffobj_Rewind(msg); return RPROT_ERR_REQD_TLV_MISSING; }
//Encrypted settings for M7 //ES when M7 is from an enrollee void CTlvEsM7Enr::parse(BufferObj &theBuf, BufferObj &authKey, bool allocate) { nonce = CTlvNonce(WSC_ID_E_SNONCE2, theBuf, SIZE_128_BITS); if(WSC_ID_IDENTITY_PROOF == theBuf.NextType()) idProof = CTlvIdentityProof(WSC_ID_IDENTITY_PROOF, theBuf, 0, allocate); // Skip attributes until the KeyWrapAuthenticator while(WSC_ID_KEY_WRAP_AUTH != theBuf.NextType()) { //advance past the TLV uint8 *Pos = theBuf.Advance( sizeof(S_WSC_TLV_HEADER) + WscNtohs(*(uint16 *)(theBuf.Pos()+sizeof(uint16))) ); //If Advance returned NULL, it means there's no more data in the //buffer. This is an error. if(Pos == NULL) throw RPROT_ERR_REQD_TLV_MISSING; } uint8 * startOfAuthenticator = theBuf.Pos(); keyWrapAuth = CTlvAuthenticator(WSC_ID_KEY_WRAP_AUTH, theBuf, SIZE_64_BITS); //validate the mac uint8 dataMac[BUF_SIZE_256_BITS]; //calculate the hmac of the data (data only, not the last auth TLV) if(HMAC(EVP_sha256(), authKey.GetBuf(), SIZE_256_BITS, theBuf.GetBuf(), startOfAuthenticator - theBuf.GetBuf(), dataMac, NULL) == NULL) { TUTRACE((TUTRACE_ERR, "RPROTO: HMAC failed\n")); throw RPROT_ERR_CRYPTO; } //compare it against the received hmac if(memcmp(dataMac, keyWrapAuth.Value(), SIZE_64_BITS) != 0) { TUTRACE((TUTRACE_ERR, "RPROTO: HMAC results don't match\n")); throw RPROT_ERR_INVALID_VALUE; } }