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)); }
/* 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_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; }
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; }
static uint32 ap_eap_sm_create_pkt(char * dataBuffer, int dataLen, uint8 eapCode) { eapol_header_t *eapolHdr = (eapol_header_t *)apEapState->msg_to_send; WpsEapHdr *wpsEapHdr; int LF_bytes = EAP_WPS_LF_OFFSET; /* Shift EAP_WPS_LF_OFFSET */ if (dataLen < apEapState->eap_frag_threshold) { eapolHdr = (eapol_header_t *)&apEapState->msg_to_send[EAP_WPS_LF_OFFSET]; LF_bytes = 0; } /* Construct EAP header */ wpsEapHdr = (WpsEapHdr *)eapolHdr->body; wpsEapHdr->code = eapCode; wpsEapHdr->id = apEapState->eap_id; wpsEapHdr->length = WpsHtons(sizeof(WpsEapHdr) + dataLen); 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); if (dataBuffer) { if (dataBuffer[WPS_MSGTYPE_OFFSET] >= WPS_ID_MESSAGE_M1 && dataBuffer[WPS_MSGTYPE_OFFSET] <= WPS_ID_MESSAGE_M8) { wpsEapHdr->opcode = WPS_MSG; } else if (dataBuffer[WPS_MSGTYPE_OFFSET] == WPS_ID_MESSAGE_ACK) { wpsEapHdr->opcode = WPS_ACK; } else if (dataBuffer[WPS_MSGTYPE_OFFSET] == WPS_ID_MESSAGE_NACK) { wpsEapHdr->opcode = WPS_NACK; } else if (dataBuffer[WPS_MSGTYPE_OFFSET] == WPS_ID_MESSAGE_DONE) { wpsEapHdr->opcode = WPS_Done; } else { TUTRACE((TUTRACE_ERR, "Unknown Message Type code %d; " "Not sending msg\n", dataBuffer[WPS_MSGTYPE_OFFSET])); return TREAP_ERR_SENDRECV; } /* record the out message id, we don't save fragmented sent_msg_id */ apEapState->sent_msg_id = dataBuffer[WPS_MSGTYPE_OFFSET]; if (apEapState->sent_msg_id == WPS_ID_MESSAGE_M2) apEapState->flags |= AP_EAP_SM_M2_SENT; /* TBD: Flags are always set to zero for now, if message is too big */ /* * fragmentation must be done here and flags will have some bits set * and message length field is added */ /* Default flags are set to zero, let ap_eap_sm_sendEap to handle it */ wpsEapHdr->flags = 0; /* in case we passed this buffer to the protocol, do not copy :-) */ if (dataBuffer - LF_bytes != (char *)(wpsEapHdr + 1)) memcpy((char *)wpsEapHdr + sizeof(WpsEapHdr) + LF_bytes, dataBuffer, dataLen); } return WPS_SUCCESS; }
uint32 reg_proto_generate_prebuild_dhkeypair(DH **DHKeyPair, BufferObj *pubKey, uint8 *prebuild_privkey) { BIGNUM *pub_key = NULL, *priv_key = NULL; BN_CTX *ctx = NULL; BN_MONT_CTX *mont; uint8 temp[SIZE_PUB_KEY]; uint32 g = 0; uint32 ret = RPROT_ERR_CRYPTO; *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 */ ctx = BN_CTX_new(); if (ctx == NULL) goto err; priv_key = BN_new(); if (priv_key == NULL) goto err; pub_key = BN_new(); if (pub_key == NULL) goto err; if (!BN_bin2bn(prebuild_privkey, SIZE_PUB_KEY, priv_key)) goto err; if ((*DHKeyPair)->flags & DH_FLAG_CACHE_MONT_P) { if (((*DHKeyPair)->method_mont_p = BN_MONT_CTX_new()) != NULL) if (!BN_MONT_CTX_set((BN_MONT_CTX *)(*DHKeyPair)->method_mont_p, (*DHKeyPair)->p, ctx)) goto err; } mont = (BN_MONT_CTX *)(*DHKeyPair)->method_mont_p; if ((*DHKeyPair)->g->top == 1) { BN_ULONG A = (*DHKeyPair)->g->d[0]; if (!BN_mod_exp_mont_word(pub_key, A, priv_key, (*DHKeyPair)->p, ctx, mont)) goto err; } else if (!BN_mod_exp_mont(pub_key, (*DHKeyPair)->g, priv_key, (*DHKeyPair)->p, ctx, mont)) goto err; (*DHKeyPair)->pub_key = pub_key; (*DHKeyPair)->priv_key = priv_key; if (BN_num_bytes((*DHKeyPair)->pub_key) == 0) goto err; /* 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")); goto err; } buffobj_Append(pubKey, SIZE_PUB_KEY, temp); ret = WPS_SUCCESS; err: if ((pub_key != NULL) && ((*DHKeyPair)->pub_key == NULL)) BN_free(pub_key); if ((priv_key != NULL) && ((*DHKeyPair)->priv_key == NULL)) BN_free(priv_key); if (ctx) BN_CTX_free(ctx); return ret; }