int main(int argc, char **argv) { uint8 output[AKW_MAX_WRAP_LEN+AKW_BLOCK_LEN]; uint8 input2[AKW_MAX_WRAP_LEN]; int retv, k, fail = 0; for (k = 0; k < NUM_VECTORS; k++) { retv = aes_wrap(akw_vec[k].kl, akw_vec[k].key, akw_vec[k].il, akw_vec[k].input, output); pres("\n AES Wrap: ", akw_vec[k].il+AKW_BLOCK_LEN, output); if (retv) { dbg(("%s: aes_wrap failed\n", *argv)); fail++; } if (memcmp(output, akw_vec[k].ref, akw_vec[k].il+AKW_BLOCK_LEN) != 0) { dbg(("%s: aes_wrap failed\n", *argv)); fail++; } retv = aes_unwrap(akw_vec[k].kl, akw_vec[k].key, akw_vec[k].il + AKW_BLOCK_LEN, output, input2); pres("\n AES Unwrap: ", akw_vec[k].il, input2); if (retv) { dbg(("%s: aes_unwrap failed\n", *argv)); fail++; } if (memcmp(akw_vec[k].input, input2, akw_vec[k].il) != 0) { dbg(("%s: aes_unwrap failed\n", *argv)); fail++; } } for (k = 0; k < NUM_WRAP_FAIL_VECTORS; k++) { if (!aes_wrap(akw_wrap_fail_vec[k].kl, akw_wrap_fail_vec[k].key, akw_wrap_fail_vec[k].il, akw_wrap_fail_vec[k].input, output)) { dbg(("%s: aes_wrap didn't detect failure case\n", *argv)); fail++; } } for (k = 0; k < NUM_UNWRAP_FAIL_VECTORS; k++) { if (!aes_unwrap(akw_unwrap_fail_vec[k].kl, akw_unwrap_fail_vec[k].key, akw_unwrap_fail_vec[k].il, akw_unwrap_fail_vec[k].input, input2)) { dbg(("%s: aes_unwrap didn't detect failure case\n", *argv)); fail++; } } dbg(("%s: %s\n", *argv, fail?"FAILED":"PASSED")); return (fail); }
static u8 * decrypt_eapol_key_data_aes(const u8 *kek, const struct wpa_eapol_key *hdr, size_t *len) { u8 *buf; u16 keydatalen = WPA_GET_BE16(hdr->key_data_length); if (keydatalen % 8) { wpa_printf(MSG_INFO, "Unsupported AES-WRAP len %d", keydatalen); return NULL; } keydatalen -= 8; /* AES-WRAP adds 8 bytes */ buf = os_malloc(keydatalen); if (buf == NULL) return NULL; if (aes_unwrap(kek, keydatalen / 8, (u8 *) (hdr + 1), buf)) { os_free(buf); wpa_printf(MSG_INFO, "AES unwrap failed - " "could not decrypt EAPOL-Key key data"); return NULL; } *len = keydatalen; return buf; }
/* Decrypt RSN EAPOL-Key key data (RC4 or AES-WRAP) */ static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm, struct wpa_eapol_key *key, u16 ver) { u16 keydatalen = WPA_GET_BE16(key->key_data_length); wpa_hexdump(MSG_DEBUG, "RSN: encrypted key data", (u8 *) (key + 1), keydatalen); if (!sm->ptk_set) { wpa_printf(MSG_WARNING, "WPA: PTK not available, " "cannot decrypt EAPOL-Key key data."); return -1; } /* Decrypt key data here so that this operation does not need * to be implemented separately for each message type. */ if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4) { u8 ek[32]; os_memcpy(ek, key->key_iv, 16); os_memcpy(ek + 16, sm->ptk.kek, 16); if (rc4_skip(ek, 32, 256, (u8 *) (key + 1), keydatalen)) { wpa_printf(MSG_ERROR, "WPA: RC4 failed"); return -1; } } else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES || ver == WPA_KEY_INFO_TYPE_AES_128_CMAC) { u8 *buf; if (keydatalen % 8) { wpa_printf(MSG_WARNING, "WPA: Unsupported " "AES-WRAP len %d", keydatalen); return -1; } keydatalen -= 8; /* AES-WRAP adds 8 bytes */ buf = os_malloc(keydatalen); if (buf == NULL) { wpa_printf(MSG_WARNING, "WPA: No memory for " "AES-UNWRAP buffer"); return -1; } if (aes_unwrap(sm->ptk.kek, keydatalen / 8, (u8 *) (key + 1), buf)) { os_free(buf); wpa_printf(MSG_WARNING, "WPA: AES unwrap failed - " "could not decrypt EAPOL-Key key data"); return -1; } os_memcpy(key + 1, buf, keydatalen); os_free(buf); WPA_PUT_BE16(key->key_data_length, keydatalen); } else { wpa_printf(MSG_WARNING, "WPA: Unsupported key_info type %d", ver); return -1; } wpa_hexdump_key(MSG_DEBUG, "WPA: decrypted EAPOL-Key key data", (u8 *) (key + 1), keydatalen); return 0; }
static int wpa_ft_process_igtk_subelem(struct wpa_sm *sm, const u8 *igtk_elem, size_t igtk_elem_len) { u8 igtk[WPA_IGTK_LEN]; u16 keyidx; if (sm->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC) return 0; if (igtk_elem == NULL) { wpa_printf(MSG_DEBUG, "FT: No IGTK included in FTIE"); return 0; } wpa_hexdump_key(MSG_DEBUG, "FT: Received IGTK in Reassoc Resp", igtk_elem, igtk_elem_len); if (igtk_elem_len != 2 + 6 + 1 + WPA_IGTK_LEN + 8) { wpa_printf(MSG_DEBUG, "FT: Invalid IGTK sub-elem " "length %lu", (unsigned long) igtk_elem_len); return -1; } if (igtk_elem[8] != WPA_IGTK_LEN) { wpa_printf(MSG_DEBUG, "FT: Invalid IGTK sub-elem Key Length " "%d", igtk_elem[8]); return -1; } if (aes_unwrap(sm->ptk.kek, sm->ptk.kek_len, WPA_IGTK_LEN / 8, igtk_elem + 9, igtk)) { wpa_printf(MSG_WARNING, "FT: AES unwrap failed - could not " "decrypt IGTK"); return -1; } /* KeyID[2] | IPN[6] | Key Length[1] | Key[16+8] */ keyidx = WPA_GET_LE16(igtk_elem); wpa_hexdump_key(MSG_DEBUG, "FT: IGTK from Reassoc Resp", igtk, WPA_IGTK_LEN); if (wpa_sm_set_key(sm, WPA_ALG_IGTK, broadcast_ether_addr, keyidx, 0, igtk_elem + 2, 6, igtk, WPA_IGTK_LEN) < 0) { wpa_printf(MSG_WARNING, "WPA: Failed to set IGTK to the " "driver."); return -1; } return 0; }
/* Decrypt RSN EAPOL-Key key data (RC4 or AES-WRAP) */ static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm, struct wpa_eapol_key *key, u16 ver) { u16 keydatalen = WPA_GET_BE16(key->key_data_length); wpa_hexdump(MSG_DEBUG, "RSN: encrypted key data",(u8 *) (key + 1), keydatalen); if (!sm->ptk_set) //wpa_supplicant_verify_eapol_key_mic ÖÐÉèÖÃ { lwip_log("WPA: PTK not available, cannot decrypt EAPOL-Key key data.\n"); return -1; } /* Decrypt key data here so that this operation does not need * to be implemented separately for each message type. */ if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4) { u8 ek[32]; os_memcpy(ek, key->key_iv, 16); os_memcpy(ek + 16, sm->ptk.kek, 16); rc4_skip(ek, 32, 256, (u8 *) (key + 1), keydatalen); } else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { u8 buf[512]; if (keydatalen % 8) { lwip_log("WPA: Unsupported AES-WRAP len %d\n", keydatalen); return -1; } keydatalen -= 8; /* AES-WRAP adds 8 bytes */ if (buf == NULL) { lwip_log("WPA: No memory for AES-UNWRAP buffer\n"); return -1; } if (aes_unwrap(sm->ptk.kek, keydatalen / 8, (u8 *)(key + 1), buf)) { lwip_log("WPA: AES unwrap failed - could not decrypt EAPOL-Key key data\n"); return -1; } os_memcpy(key + 1, buf, keydatalen); WPA_PUT_BE16(key->key_data_length, keydatalen); } wpa_hexdump_key(MSG_DEBUG, "WPA: decrypted EAPOL-Key key data", (u8*)(key + 1), keydatalen); return 0; }
/* Decrypt a key data from a WPA key message */ bool BCMROMFN(wpa_decr_key_data)(eapol_wpa_key_header_t *body, uint16 key_info, uint8 *ekey, uint8 *gtk, uint8 *data, uint8 *encrkey, rc4_ks_t *rc4key) { uint16 len; switch (key_info & (WPA_KEY_DESC_V1 | WPA_KEY_DESC_V2)) { case WPA_KEY_DESC_V1: bcopy(body->iv, encrkey, WPA_MIC_KEY_LEN); bcopy(ekey, &encrkey[WPA_MIC_KEY_LEN], WPA_MIC_KEY_LEN); /* decrypt the key data */ prepare_key(encrkey, WPA_MIC_KEY_LEN*2, rc4key); rc4(data, WPA_KEY_DATA_LEN_256, rc4key); /* dump 256 bytes */ if (gtk) len = ntoh16_ua((uint8 *)&body->key_len); else len = ntoh16_ua((uint8 *)&body->data_len); rc4(body->data, len, rc4key); if (gtk) bcopy(body->data, gtk, len); break; case WPA_KEY_DESC_V2: case WPA_KEY_DESC_V3: len = ntoh16_ua((uint8 *)&body->data_len); if (aes_unwrap(WPA_MIC_KEY_LEN, ekey, len, body->data, gtk ? gtk : body->data)) { return FALSE; } break; default: return FALSE; } return TRUE; }
static int wpa_ft_rrb_rx_pull(struct wpa_authenticator *wpa_auth, const u8 *src_addr, const u8 *data, size_t data_len) { struct ft_r0kh_r1kh_pull_frame *frame, f; struct ft_remote_r1kh *r1kh; struct ft_r0kh_r1kh_resp_frame resp, r; u8 pmk_r0[PMK_LEN]; int pairwise; wpa_printf(MSG_DEBUG, "FT: Received PMK-R1 pull"); if (data_len < sizeof(*frame)) return -1; r1kh = wpa_auth->conf.r1kh_list; while (r1kh) { if (os_memcmp(r1kh->addr, src_addr, ETH_ALEN) == 0) break; r1kh = r1kh->next; } if (r1kh == NULL) { wpa_printf(MSG_DEBUG, "FT: No matching R1KH address found for " "PMK-R1 pull source address " MACSTR, MAC2STR(src_addr)); return -1; } frame = (struct ft_r0kh_r1kh_pull_frame *) data; /* aes_unwrap() does not support inplace decryption, so use a temporary * buffer for the data. */ if (aes_unwrap(r1kh->key, (FT_R0KH_R1KH_PULL_DATA_LEN + 7) / 8, frame->nonce, f.nonce) < 0) { wpa_printf(MSG_DEBUG, "FT: Failed to decrypt PMK-R1 pull " "request from " MACSTR, MAC2STR(src_addr)); return -1; } wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - nonce", f.nonce, sizeof(f.nonce)); wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - PMKR0Name", f.pmk_r0_name, WPA_PMK_NAME_LEN); wpa_printf(MSG_DEBUG, "FT: PMK-R1 pull - R1KH-ID=" MACSTR "S1KH-ID=" MACSTR, MAC2STR(f.r1kh_id), MAC2STR(f.s1kh_id)); os_memset(&resp, 0, sizeof(resp)); resp.frame_type = RSN_REMOTE_FRAME_TYPE_FT_RRB; resp.packet_type = FT_PACKET_R0KH_R1KH_RESP; resp.data_length = host_to_le16(FT_R0KH_R1KH_RESP_DATA_LEN); os_memcpy(resp.ap_address, wpa_auth->addr, ETH_ALEN); /* aes_wrap() does not support inplace encryption, so use a temporary * buffer for the data. */ os_memcpy(r.nonce, f.nonce, sizeof(f.nonce)); os_memcpy(r.r1kh_id, f.r1kh_id, FT_R1KH_ID_LEN); os_memcpy(r.s1kh_id, f.s1kh_id, ETH_ALEN); if (wpa_ft_fetch_pmk_r0(wpa_auth, f.s1kh_id, f.pmk_r0_name, pmk_r0, &pairwise) < 0) { wpa_printf(MSG_DEBUG, "FT: No matching PMKR0Name found for " "PMK-R1 pull"); return -1; } wpa_derive_pmk_r1(pmk_r0, f.pmk_r0_name, f.r1kh_id, f.s1kh_id, r.pmk_r1, r.pmk_r1_name); wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", r.pmk_r1, PMK_LEN); wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", r.pmk_r1_name, WPA_PMK_NAME_LEN); r.pairwise = host_to_le16(pairwise); if (aes_wrap(r1kh->key, (FT_R0KH_R1KH_RESP_DATA_LEN + 7) / 8, r.nonce, resp.nonce) < 0) { os_memset(pmk_r0, 0, PMK_LEN); return -1; } os_memset(pmk_r0, 0, PMK_LEN); wpa_ft_rrb_send(wpa_auth, src_addr, (u8 *) &resp, sizeof(resp)); return 0; }
static int wpa_ft_process_gtk_subelem(struct wpa_sm *sm, const u8 *gtk_elem, size_t gtk_elem_len) { u8 gtk[32]; int keyidx; enum wpa_alg alg; size_t gtk_len, keylen, rsc_len; if (gtk_elem == NULL) { wpa_printf(MSG_DEBUG, "FT: No GTK included in FTIE"); return 0; } wpa_hexdump_key(MSG_DEBUG, "FT: Received GTK in Reassoc Resp", gtk_elem, gtk_elem_len); if (gtk_elem_len < 11 + 24 || (gtk_elem_len - 11) % 8 || gtk_elem_len - 19 > sizeof(gtk)) { wpa_printf(MSG_DEBUG, "FT: Invalid GTK sub-elem " "length %lu", (unsigned long) gtk_elem_len); return -1; } gtk_len = gtk_elem_len - 19; if (aes_unwrap(sm->ptk.kek, sm->ptk.kek_len, gtk_len / 8, gtk_elem + 11, gtk)) { wpa_printf(MSG_WARNING, "FT: AES unwrap failed - could not " "decrypt GTK"); return -1; } keylen = wpa_cipher_key_len(sm->group_cipher); rsc_len = wpa_cipher_rsc_len(sm->group_cipher); alg = wpa_cipher_to_alg(sm->group_cipher); if (alg == WPA_ALG_NONE) { wpa_printf(MSG_WARNING, "WPA: Unsupported Group Cipher %d", sm->group_cipher); return -1; } if (gtk_len < keylen) { wpa_printf(MSG_DEBUG, "FT: Too short GTK in FTIE"); return -1; } /* Key Info[2] | Key Length[1] | RSC[8] | Key[5..32]. */ keyidx = WPA_GET_LE16(gtk_elem) & 0x03; if (gtk_elem[2] != keylen) { wpa_printf(MSG_DEBUG, "FT: GTK length mismatch: received %d " "negotiated %lu", gtk_elem[2], (unsigned long) keylen); return -1; } wpa_hexdump_key(MSG_DEBUG, "FT: GTK from Reassoc Resp", gtk, keylen); if (sm->group_cipher == WPA_CIPHER_TKIP) { /* Swap Tx/Rx keys for Michael MIC */ u8 tmp[8]; os_memcpy(tmp, gtk + 16, 8); os_memcpy(gtk + 16, gtk + 24, 8); os_memcpy(gtk + 24, tmp, 8); } if (wpa_sm_set_key(sm, alg, broadcast_ether_addr, keyidx, 0, gtk_elem + 3, rsc_len, gtk, keylen) < 0) { wpa_printf(MSG_WARNING, "WPA: Failed to set GTK to the " "driver."); return -1; } return 0; }
int main(int argc, char *argv[]) { u8 kek[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }; u8 plain[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }; u8 crypt[] = { 0x1F, 0xA6, 0x8B, 0x0A, 0x81, 0x12, 0xB4, 0x47, 0xAE, 0xF3, 0x4B, 0xD8, 0xFB, 0x5A, 0x7B, 0x82, 0x9D, 0x3E, 0x86, 0x23, 0x71, 0xD2, 0xCF, 0xE5 }; u8 result[24]; int ret = 0; unsigned int i; struct omac1_test_vector *tv; if (aes_wrap(kek, 2, plain, result)) { printf("AES-WRAP-128-128 reported failure\n"); ret++; } if (memcmp(result, crypt, 24) != 0) { printf("AES-WRAP-128-128 failed\n"); ret++; } if (aes_unwrap(kek, 2, crypt, result)) { printf("AES-UNWRAP-128-128 reported failure\n"); ret++; } if (memcmp(result, plain, 16) != 0) { printf("AES-UNWRAP-128-128 failed\n"); ret++; for (i = 0; i < 16; i++) printf(" %02x", result[i]); printf("\n"); } test_aes_perf(); for (i = 0; i < ARRAY_SIZE(test_vectors); i++) { tv = &test_vectors[i]; if (omac1_aes_128(tv->k, tv->msg, tv->msg_len, result) || memcmp(result, tv->tag, 16) != 0) { printf("OMAC1-AES-128 test vector %d failed\n", i); ret++; } if (tv->msg_len > 1) { const u8 *addr[2]; size_t len[2]; addr[0] = tv->msg; len[0] = 1; addr[1] = tv->msg + 1; len[1] = tv->msg_len - 1; if (omac1_aes_128_vector(tv->k, 2, addr, len, result) || memcmp(result, tv->tag, 16) != 0) { printf("OMAC1-AES-128(vector) test vector %d " "failed\n", i); ret++; } } } ret += test_eax(); ret += test_cbc(); ret += test_gcm(); if (ret) printf("FAILED!\n"); return ret; }
static bRC do_set_scsi_encryption_key(void *value) { DCR *dcr; DEVICE *dev; DEVRES *device; DIRRES *director; char StoredVolEncrKey[MAX_NAME_LENGTH]; char VolEncrKey[MAX_NAME_LENGTH]; /* * Unpack the arguments passed in. */ dcr = (DCR *)value; if (!dcr) { return bRC_Error; } dev = dcr->dev; if (!dev) { return bRC_Error; } device = dev->device; if (!device) { return bRC_Error; } *StoredVolEncrKey = '\0'; if (!get_volume_encryption_key(dcr, StoredVolEncrKey)) { return bRC_Error; } /* * See if a volume encryption key is available. */ if (!*StoredVolEncrKey) { Dmsg0(dbglvl, "scsicrypto-sd: No encryption key to load on device\n"); return bRC_OK; } /* * See if device supports hardware encryption. */ if (!device->drive_crypto_enabled) { Dmsg0(dbglvl, "scsicrypto-sd: Trying to load encryption key on drive without support\n"); Emsg0(M_ERROR, 0, _("scsicrypto-sd: Trying to load encryption key on drive without support\n")); return bRC_Error; } /* * The key passed from the director to the storage daemon is always base64 encoded. */ base64_to_bin(VolEncrKey, sizeof(VolEncrKey), StoredVolEncrKey, strlen(StoredVolEncrKey)); /* * See if we have an key encryption key in the config then the passed key * has been wrapped using RFC3394 key wrapping. We first copy the current * wrapped key into a temporary variable for unwrapping. */ if (dcr->jcr && dcr->jcr->director) { director = dcr->jcr->director; if (director->keyencrkey) { char WrappedVolEncrKey[MAX_NAME_LENGTH]; memcpy(WrappedVolEncrKey, VolEncrKey, MAX_NAME_LENGTH); memset(VolEncrKey, 0, MAX_NAME_LENGTH); if (aes_unwrap((unsigned char *)director->keyencrkey, DEFAULT_PASSPHRASE_LENGTH / 8, (unsigned char *)WrappedVolEncrKey, (unsigned char *)VolEncrKey) != 0) { Dmsg1(dbglvl, "scsicrypto-sd: Failed to unwrap encryption key using %s\n", director->keyencrkey); Emsg0(M_ERROR, 0, _("scsicrypto-sd: Failed to unwrap encryption key, probably wrong KeyEncryptionKey in config\n")); return bRC_Error; } } } Dmsg1(dbglvl, "scsicrypto-sd: Loading new crypto key %s\n", VolEncrKey); P(crypto_operation_mutex); if (set_scsi_encryption_key(dev->fd(), dev->dev_name, VolEncrKey)) { dev->set_crypto_enabled(); V(crypto_operation_mutex); return bRC_OK; } else { V(crypto_operation_mutex); return bRC_Error; } }
static int eap_fast_session_ticket_cb(void *ctx, const u8 *ticket, size_t len, const u8 *client_random, const u8 *server_random, u8 *master_secret) { struct eap_fast_data *data = ctx; const u8 *pac_opaque; size_t pac_opaque_len; u8 *buf, *pos, *end, *pac_key = NULL; os_time_t lifetime = 0; struct os_time now; u8 *identity = NULL; size_t identity_len = 0; wpa_printf(MSG_DEBUG, "EAP-FAST: SessionTicket callback"); wpa_hexdump(MSG_DEBUG, "EAP-FAST: SessionTicket (PAC-Opaque)", ticket, len); if (len < 4 || WPA_GET_BE16(ticket) != PAC_TYPE_PAC_OPAQUE) { wpa_printf(MSG_DEBUG, "EAP-FAST: Ignore invalid " "SessionTicket"); return 0; } pac_opaque_len = WPA_GET_BE16(ticket + 2); pac_opaque = ticket + 4; if (pac_opaque_len < 8 || pac_opaque_len % 8 || pac_opaque_len > len - 4) { wpa_printf(MSG_DEBUG, "EAP-FAST: Ignore invalid PAC-Opaque " "(len=%lu left=%lu)", (unsigned long) pac_opaque_len, (unsigned long) len); return 0; } wpa_hexdump(MSG_DEBUG, "EAP-FAST: Received PAC-Opaque", pac_opaque, pac_opaque_len); buf = os_malloc(pac_opaque_len - 8); if (buf == NULL) { wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to allocate memory " "for decrypting PAC-Opaque"); return 0; } if (aes_unwrap(data->pac_opaque_encr, sizeof(data->pac_opaque_encr), (pac_opaque_len - 8) / 8, pac_opaque, buf) < 0) { wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to decrypt " "PAC-Opaque"); os_free(buf); /* * This may have been caused by server changing the PAC-Opaque * encryption key, so just ignore this PAC-Opaque instead of * failing the authentication completely. Provisioning can now * be used to provision a new PAC. */ return 0; } end = buf + pac_opaque_len - 8; wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Decrypted PAC-Opaque", buf, end - buf); pos = buf; while (end - pos > 1) { u8 id, elen; id = *pos++; elen = *pos++; if (elen > end - pos) break; switch (id) { case PAC_OPAQUE_TYPE_PAD: goto done; case PAC_OPAQUE_TYPE_KEY: if (elen != EAP_FAST_PAC_KEY_LEN) { wpa_printf(MSG_DEBUG, "EAP-FAST: Invalid PAC-Key length %d", elen); os_free(buf); return -1; } pac_key = pos; wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: PAC-Key from " "decrypted PAC-Opaque", pac_key, EAP_FAST_PAC_KEY_LEN); break; case PAC_OPAQUE_TYPE_LIFETIME: if (elen != 4) { wpa_printf(MSG_DEBUG, "EAP-FAST: Invalid " "PAC-Key lifetime length %d", elen); os_free(buf); return -1; } lifetime = WPA_GET_BE32(pos); break; case PAC_OPAQUE_TYPE_IDENTITY: identity = pos; identity_len = elen; break; } pos += elen; } done: if (pac_key == NULL) { wpa_printf(MSG_DEBUG, "EAP-FAST: No PAC-Key included in " "PAC-Opaque"); os_free(buf); return -1; } if (identity) { wpa_hexdump_ascii(MSG_DEBUG, "EAP-FAST: Identity from " "PAC-Opaque", identity, identity_len); os_free(data->identity); data->identity = os_malloc(identity_len); if (data->identity) { os_memcpy(data->identity, identity, identity_len); data->identity_len = identity_len; } } if (os_get_time(&now) < 0 || lifetime <= 0 || now.sec > lifetime) { wpa_printf(MSG_DEBUG, "EAP-FAST: PAC-Key not valid anymore " "(lifetime=%ld now=%ld)", lifetime, now.sec); data->send_new_pac = 2; /* * Allow PAC to be used to allow a PAC update with some level * of server authentication (i.e., do not fall back to full TLS * handshake since we cannot be sure that the peer would be * able to validate server certificate now). However, reject * the authentication since the PAC was not valid anymore. Peer * can connect again with the newly provisioned PAC after this. */ } else if (lifetime - now.sec < data->pac_key_refresh_time) { wpa_printf(MSG_DEBUG, "EAP-FAST: PAC-Key soft timeout; send " "an update if authentication succeeds"); data->send_new_pac = 1; } eap_fast_derive_master_secret(pac_key, server_random, client_random, master_secret); os_free(buf); return 1; }
static int wpa_ft_process_gtk_subelem(struct wpa_sm *sm, const u8 *gtk_elem, size_t gtk_elem_len) { u8 gtk[32]; int keyidx; wpa_alg alg; size_t gtk_len, keylen, rsc_len; if (gtk_elem == NULL) { wpa_printf(MSG_DEBUG, "FT: No GTK included in FTIE"); return 0; } wpa_hexdump_key(MSG_DEBUG, "FT: Received GTK in Reassoc Resp", gtk_elem, gtk_elem_len); if (gtk_elem_len < 10 + 24 || (gtk_elem_len - 10) % 8 || gtk_elem_len - 18 > sizeof(gtk)) { wpa_printf(MSG_DEBUG, "FT: Invalid GTK sub-elem " "length %lu", (unsigned long) gtk_elem_len); return -1; } gtk_len = gtk_elem_len - 18; if (aes_unwrap(sm->ptk.kek, gtk_len / 8, gtk_elem + 10, gtk)) { wpa_printf(MSG_WARNING, "FT: AES unwrap failed - could not " "decrypt GTK"); return -1; } switch (sm->group_cipher) { case WPA_CIPHER_CCMP: keylen = 16; rsc_len = 6; alg = WPA_ALG_CCMP; break; case WPA_CIPHER_TKIP: keylen = 32; rsc_len = 6; alg = WPA_ALG_TKIP; break; case WPA_CIPHER_WEP104: keylen = 13; rsc_len = 0; alg = WPA_ALG_WEP; break; case WPA_CIPHER_WEP40: keylen = 5; rsc_len = 0; alg = WPA_ALG_WEP; break; default: wpa_printf(MSG_WARNING, "WPA: Unsupported Group Cipher %d", sm->group_cipher); return -1; } if (gtk_len < keylen) { wpa_printf(MSG_DEBUG, "FT: Too short GTK in FTIE"); return -1; } /* Key Info[1] | Key Length[1] | RSC[8] | Key[5..32]. */ keyidx = gtk_elem[0] & 0x03; if (gtk_elem[1] != keylen) { wpa_printf(MSG_DEBUG, "FT: GTK length mismatch: received %d " "negotiated %lu", gtk_elem[1], (unsigned long) keylen); return -1; } wpa_hexdump_key(MSG_DEBUG, "FT: GTK from Reassoc Resp", gtk, keylen); if (wpa_sm_set_key(sm, alg, (u8 *) "\xff\xff\xff\xff\xff\xff", keyidx, 0, gtk_elem + 2, rsc_len, gtk, keylen) < 0) { wpa_printf(MSG_WARNING, "WPA: Failed to set GTK to the " "driver."); return -1; } return 0; }
static int wpa_ft_rrb_rx_resp(struct wpa_authenticator *wpa_auth, const u8 *src_addr, const u8 *data, size_t data_len) { struct ft_r0kh_r1kh_resp_frame *frame, f; struct ft_remote_r0kh *r0kh; int pairwise; wpa_printf(MSG_DEBUG, "FT: Received PMK-R1 pull response"); if (data_len < sizeof(*frame)) return -1; r0kh = wpa_auth->conf.r0kh_list; while (r0kh) { if (os_memcmp(r0kh->addr, src_addr, ETH_ALEN) == 0) break; r0kh = r0kh->next; } if (r0kh == NULL) { wpa_printf(MSG_DEBUG, "FT: No matching R0KH address found for " "PMK-R0 pull response source address " MACSTR, MAC2STR(src_addr)); return -1; } frame = (struct ft_r0kh_r1kh_resp_frame *) data; /* aes_unwrap() does not support inplace decryption, so use a temporary * buffer for the data. */ if (aes_unwrap(r0kh->key, (FT_R0KH_R1KH_RESP_DATA_LEN + 7) / 8, frame->nonce, f.nonce) < 0) { wpa_printf(MSG_DEBUG, "FT: Failed to decrypt PMK-R1 pull " "response from " MACSTR, MAC2STR(src_addr)); return -1; } if (os_memcmp(f.r1kh_id, wpa_auth->conf.r1_key_holder, FT_R1KH_ID_LEN) != 0) { wpa_printf(MSG_DEBUG, "FT: PMK-R1 pull response did not use a " "matching R1KH-ID"); return -1; } /* TODO: verify that <nonce,s1kh_id> matches with a pending request * and call this requests callback function to finish request * processing */ pairwise = le_to_host16(f.pairwise); wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - nonce", f.nonce, sizeof(f.nonce)); wpa_printf(MSG_DEBUG, "FT: PMK-R1 pull - R1KH-ID=" MACSTR "S1KH-ID=" MACSTR " pairwise=0x%x", MAC2STR(f.r1kh_id), MAC2STR(f.s1kh_id), pairwise); wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1 pull - PMK-R1", f.pmk_r1, PMK_LEN); wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - PMKR1Name", f.pmk_r1_name, WPA_PMK_NAME_LEN); wpa_ft_store_pmk_r1(wpa_auth, f.s1kh_id, f.pmk_r1, f.pmk_r1_name, pairwise); os_memset(f.pmk_r1, 0, PMK_LEN); return 0; }
static int wpa_ft_rrb_rx_push(struct wpa_authenticator *wpa_auth, const u8 *src_addr, const u8 *data, size_t data_len) { struct ft_r0kh_r1kh_push_frame *frame, f; struct ft_remote_r0kh *r0kh; struct os_time now; os_time_t tsend; int pairwise; wpa_printf(MSG_DEBUG, "FT: Received PMK-R1 push"); if (data_len < sizeof(*frame)) return -1; r0kh = wpa_auth->conf.r0kh_list; while (r0kh) { if (os_memcmp(r0kh->addr, src_addr, ETH_ALEN) == 0) break; r0kh = r0kh->next; } if (r0kh == NULL) { wpa_printf(MSG_DEBUG, "FT: No matching R0KH address found for " "PMK-R0 push source address " MACSTR, MAC2STR(src_addr)); return -1; } frame = (struct ft_r0kh_r1kh_push_frame *) data; /* aes_unwrap() does not support inplace decryption, so use a temporary * buffer for the data. */ if (aes_unwrap(r0kh->key, (FT_R0KH_R1KH_PUSH_DATA_LEN + 7) / 8, frame->timestamp, f.timestamp) < 0) { wpa_printf(MSG_DEBUG, "FT: Failed to decrypt PMK-R1 push from " MACSTR, MAC2STR(src_addr)); return -1; } os_get_time(&now); tsend = WPA_GET_LE32(f.timestamp); if ((now.sec > tsend && now.sec - tsend > 60) || (now.sec < tsend && tsend - now.sec > 60)) { wpa_printf(MSG_DEBUG, "FT: PMK-R1 push did not have a valid " "timestamp: sender time %d own time %d\n", (int) tsend, (int) now.sec); return -1; } if (os_memcmp(f.r1kh_id, wpa_auth->conf.r1_key_holder, FT_R1KH_ID_LEN) != 0) { wpa_printf(MSG_DEBUG, "FT: PMK-R1 push did not use a matching " "R1KH-ID (received " MACSTR " own " MACSTR ")", MAC2STR(f.r1kh_id), MAC2STR(wpa_auth->conf.r1_key_holder)); return -1; } pairwise = le_to_host16(f.pairwise); wpa_printf(MSG_DEBUG, "FT: PMK-R1 push - R1KH-ID=" MACSTR " S1KH-ID=" MACSTR " pairwise=0x%x", MAC2STR(f.r1kh_id), MAC2STR(f.s1kh_id), pairwise); wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1 push - PMK-R1", f.pmk_r1, PMK_LEN); wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 push - PMKR1Name", f.pmk_r1_name, WPA_PMK_NAME_LEN); wpa_ft_store_pmk_r1(wpa_auth, f.s1kh_id, f.pmk_r1, f.pmk_r1_name, pairwise); os_memset(f.pmk_r1, 0, PMK_LEN); return 0; }
static int wpa_supplicant_process_1_of_2_wpa(struct wpa_sm *sm, const struct wpa_eapol_key *key, size_t keydatalen, int key_info, size_t extra_len, u16 ver, struct wpa_gtk_data *gd) { size_t maxkeylen; u8 ek[32]; gd->gtk_len = WPA_GET_BE16(key->key_length); maxkeylen = keydatalen; if (keydatalen > extra_len) { wpa_printf(MSG_INFO, "WPA: Truncated EAPOL-Key packet:" " key_data_length=%lu > extra_len=%lu", (unsigned long) keydatalen, (unsigned long) extra_len); return -1; } if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { if (maxkeylen < 8) { wpa_printf(MSG_INFO, "WPA: Too short maxkeylen (%lu)", (unsigned long) maxkeylen); return -1; } maxkeylen -= 8; } if (wpa_supplicant_check_group_cipher(sm->group_cipher, gd->gtk_len, maxkeylen, &gd->key_rsc_len, &gd->alg)) return -1; gd->keyidx = (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >> WPA_KEY_INFO_KEY_INDEX_SHIFT; if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4) { os_memcpy(ek, key->key_iv, 16); os_memcpy(ek + 16, sm->ptk.kek, 16); if (keydatalen > sizeof(gd->gtk)) { wpa_printf(MSG_WARNING, "WPA: RC4 key data " "too long (%lu)", (unsigned long) keydatalen); return -1; } os_memcpy(gd->gtk, key + 1, keydatalen); if (rc4_skip(ek, 32, 256, gd->gtk, keydatalen)) { wpa_printf(MSG_ERROR, "WPA: RC4 failed"); return -1; } } else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { if (keydatalen % 8) { wpa_printf(MSG_WARNING, "WPA: Unsupported AES-WRAP " "len %lu", (unsigned long) keydatalen); return -1; } if (maxkeylen > sizeof(gd->gtk)) { wpa_printf(MSG_WARNING, "WPA: AES-WRAP key data " "too long (keydatalen=%lu maxkeylen=%lu)", (unsigned long) keydatalen, (unsigned long) maxkeylen); return -1; } if (aes_unwrap(sm->ptk.kek, maxkeylen / 8, (const u8 *) (key + 1), gd->gtk)) { wpa_printf(MSG_WARNING, "WPA: AES unwrap " "failed - could not decrypt GTK"); return -1; } } else { wpa_printf(MSG_WARNING, "WPA: Unsupported key_info type %d", ver); return -1; } gd->tx = wpa_supplicant_gtk_tx_bit_workaround( sm, !!(key_info & WPA_KEY_INFO_TXRX)); return 0; }
int main(int argc, char *const *argv) { int retval = 0; int ch, kfd, length; bool base64_transform = false, clear_encryption = false, drive_encryption_status = false, generate_passphrase = false, populate_cache = false, set_encryption = false, show_keydata = false, volume_encryption_status = false, wrapped_keys = false; char *keyfile = NULL; char *cache_file = NULL; char *wrap_keyfile = NULL; char keydata[64]; char wrapdata[64]; setlocale(LC_ALL, ""); bindtextdomain("bareos", LOCALEDIR); textdomain("bareos"); while ((ch = getopt(argc, argv, "bcd:eg:k:p:s:vw:?")) != -1) { switch (ch) { case 'b': base64_transform = true; break; case 'c': clear_encryption = true; break; case 'd': debug_level = atoi(optarg); if (debug_level <= 0) { debug_level = 1; } break; case 'e': drive_encryption_status = true; break; case 'g': generate_passphrase = true; if (keyfile) { usage(); goto bail_out; } keyfile = bstrdup(optarg); break; case 'k': show_keydata = true; if (keyfile) { usage(); goto bail_out; } keyfile = bstrdup(optarg); break; case 'p': populate_cache = true; cache_file = bstrdup(optarg); break; case 's': set_encryption = true; if (keyfile) { usage(); goto bail_out; } keyfile = bstrdup(optarg); break; case 'v': volume_encryption_status = true; break; case 'w': wrapped_keys = true; wrap_keyfile = bstrdup(optarg); break; case '?': default: usage(); goto bail_out; } } argc -= optind; argv += optind; if (!generate_passphrase && !show_keydata && !populate_cache && argc < 1) { fprintf(stderr, _("Missing device_name argument for this option\n")); usage(); retval = 1; goto bail_out; } if (generate_passphrase && show_keydata) { fprintf(stderr, _("Either use -g or -k not both\n")); retval = 1; goto bail_out; } if (clear_encryption && set_encryption) { fprintf(stderr, _("Either use -c or -s not both\n")); retval = 1; goto bail_out; } if ((clear_encryption || set_encryption) && (drive_encryption_status || volume_encryption_status)) { fprintf(stderr, _("Either set or clear the crypto key or ask for status not both\n")); retval = 1; goto bail_out; } if ((clear_encryption || set_encryption || drive_encryption_status || volume_encryption_status) && (generate_passphrase || show_keydata || populate_cache)) { fprintf(stderr, _("Don't mix operations which are incompatible " "e.g. generate/show vs set/clear etc.\n")); retval = 1; goto bail_out; } OSDependentInit(); init_msg(NULL, NULL); if (populate_cache) { char *VolumeName, *EncrKey; char new_cache_entry[256]; /* * Load any keys currently in the cache. */ read_crypto_cache(cache_file); /* * Read new entries from stdin and parse them to update * the cache. */ fprintf(stdout, _("Enter cache entrie(s) (close with ^D): ")); fflush(stdout); while (read(1, new_cache_entry, sizeof(new_cache_entry)) > 0) { strip_trailing_junk(new_cache_entry); /* * Try to parse the entry. */ VolumeName = new_cache_entry; EncrKey = strchr(new_cache_entry, '\t'); if (!EncrKey) { break; } *EncrKey++ = '\0'; update_crypto_cache(VolumeName, EncrKey); } /* * Write out the new cache entries. */ write_crypto_cache(cache_file); goto bail_out; } memset(keydata, 0, sizeof(keydata)); memset(wrapdata, 0, sizeof(wrapdata)); if (wrapped_keys) { /* * Read the key bits from the keyfile. * - == stdin */ if (bstrcmp(wrap_keyfile, "-")) { kfd = 0; fprintf(stdout, _("Enter Key Encryption Key: ")); fflush(stdout); } else { kfd = open(wrap_keyfile, O_RDONLY); if (kfd < 0) { fprintf(stderr, _("Cannot open keyfile %s\n"), wrap_keyfile); retval = 1; goto bail_out; } } read(kfd, wrapdata, sizeof(wrapdata)); if (kfd > 0) { close(kfd); } strip_trailing_junk(wrapdata); Dmsg1(10, "Wrapped keydata = %s\n", wrapdata); } /* * Generate a new passphrase allow it to be wrapped using the given wrapkey * and base64 if specified or when wrapped. */ if (generate_passphrase) { int cnt; char *passphrase; passphrase = generate_crypto_passphrase(DEFAULT_PASSPHRASE_LENGTH); if (!passphrase) { retval = 1; goto bail_out; } Dmsg1(10, "Generated passphrase = %s\n", passphrase); /* * See if we need to wrap the passphrase. */ if (wrapped_keys) { char *wrapped_passphrase; length = DEFAULT_PASSPHRASE_LENGTH + 8; wrapped_passphrase = (char *)malloc(length); memset(wrapped_passphrase, 0, length); aes_wrap((unsigned char *)wrapdata, DEFAULT_PASSPHRASE_LENGTH / 8, (unsigned char *)passphrase, (unsigned char *)wrapped_passphrase); free(passphrase); passphrase = wrapped_passphrase; } else { length = DEFAULT_PASSPHRASE_LENGTH; } /* * See where to write the key. * - == stdout */ if (bstrcmp(keyfile, "-")) { kfd = 1; } else { kfd = open(keyfile, O_WRONLY | O_CREAT, 0644); if (kfd < 0) { fprintf(stderr, _("Cannot open keyfile %s\n"), keyfile); free(passphrase); retval = 1; goto bail_out; } } if (base64_transform || wrapped_keys) { cnt = bin_to_base64(keydata, sizeof(keydata), passphrase, length, true); if (write(kfd, keydata, cnt) != cnt) { fprintf(stderr, _("Failed to write %d bytes to keyfile %s\n"), cnt, keyfile); } } else { cnt = DEFAULT_PASSPHRASE_LENGTH; if (write(kfd, passphrase, cnt) != cnt) { fprintf(stderr, _("Failed to write %d bytes to keyfile %s\n"), cnt, keyfile); } } Dmsg1(10, "Keydata = %s\n", keydata); if (kfd > 1) { close(kfd); } else { write(kfd, "\n", 1); } free(passphrase); goto bail_out; } if (show_keydata) { char *passphrase; /* * Read the key bits from the keyfile. * - == stdin */ if (bstrcmp(keyfile, "-")) { kfd = 0; fprintf(stdout, _("Enter Encryption Key: ")); fflush(stdout); } else { kfd = open(keyfile, O_RDONLY); if (kfd < 0) { fprintf(stderr, _("Cannot open keyfile %s\n"), keyfile); retval = 1; goto bail_out; } } read(kfd, keydata, sizeof(keydata)); if (kfd > 0) { close(kfd); } strip_trailing_junk(keydata); Dmsg1(10, "Keydata = %s\n", keydata); /* * See if we need to unwrap the passphrase. */ if (wrapped_keys) { char *wrapped_passphrase; /* * A wrapped key is base64 encoded after it was wrapped so first * convert it from base64 to bin. As we first go from base64 to bin * and the base64_to_bin has a check if the decoded string will fit * we need to alocate some more bytes for the decoded buffer to be * sure it will fit. */ length = DEFAULT_PASSPHRASE_LENGTH + 12; wrapped_passphrase = (char *)malloc(length); memset(wrapped_passphrase, 0, length); if (base64_to_bin(wrapped_passphrase, length, keydata, strlen(keydata)) == 0) { fprintf(stderr, _("Failed to base64 decode the keydata read from %s, aborting...\n"), keyfile); free(wrapped_passphrase); goto bail_out; } length = DEFAULT_PASSPHRASE_LENGTH; passphrase = (char *)malloc(length); memset(passphrase, 0, length); if (aes_unwrap((unsigned char *)wrapdata, length / 8, (unsigned char *)wrapped_passphrase, (unsigned char *)passphrase) == -1) { fprintf(stderr, _("Failed to aes unwrap the keydata read from %s using the wrap data from %s, aborting...\n"), keyfile, wrap_keyfile); free(wrapped_passphrase); goto bail_out; } free(wrapped_passphrase); } else { if (base64_transform) { /* * As we first go from base64 to bin and the base64_to_bin has a check * if the decoded string will fit we need to alocate some more bytes * for the decoded buffer to be sure it will fit. */ length = DEFAULT_PASSPHRASE_LENGTH + 4; passphrase = (char *)malloc(length); memset(passphrase, 0, length); base64_to_bin(passphrase, length, keydata, strlen(keydata)); } else { length = DEFAULT_PASSPHRASE_LENGTH; passphrase = (char *)malloc(length); memset(passphrase, 0, length); bstrncpy(passphrase, keydata, length); } } Dmsg1(10, "Unwrapped passphrase = %s\n", passphrase); fprintf(stdout, "%s\n", passphrase); free(passphrase); goto bail_out; } /* * Clear the loaded encryption key of the given drive. */ if (clear_encryption) { if (clear_scsi_encryption_key(-1, argv[0])) { goto bail_out; } else { retval = 1; goto bail_out; } } /* * Get the drive encryption status of the given drive. */ if (drive_encryption_status) { POOLMEM *encryption_status = get_pool_memory(PM_MESSAGE); if (get_scsi_drive_encryption_status(-1, argv[0], encryption_status, 0)) { fprintf(stdout, "%s", encryption_status); free_pool_memory(encryption_status); } else { retval = 1; free_pool_memory(encryption_status); goto bail_out; } } /* * Load a new encryption key onto the given drive. */ if (set_encryption) { /* * Read the key bits from the keyfile. * - == stdin */ if (bstrcmp(keyfile, "-")) { kfd = 0; fprintf(stdout, _("Enter Encryption Key (close with ^D): ")); fflush(stdout); } else { kfd = open(keyfile, O_RDONLY); if (kfd < 0) { fprintf(stderr, _("Cannot open keyfile %s\n"), keyfile); retval = 1; goto bail_out; } } read(kfd, keydata, sizeof(keydata)); if (kfd > 0) { close(kfd); } strip_trailing_junk(keydata); if (set_scsi_encryption_key(-1, argv[0], keydata)) { goto bail_out; } else { retval = 1; goto bail_out; } } /* * Get the volume encryption status of volume currently loaded in the given drive. */ if (volume_encryption_status) { POOLMEM *encryption_status = get_pool_memory(PM_MESSAGE); if (get_scsi_volume_encryption_status(-1, argv[0], encryption_status, 0)) { fprintf(stdout, "%s", encryption_status); free_pool_memory(encryption_status); } else { retval = 1; free_pool_memory(encryption_status); goto bail_out; } } bail_out: if (cache_file) { free(cache_file); } if (keyfile) { free(keyfile); } if (wrap_keyfile) { free(wrap_keyfile); } exit(retval); }
static int test_nist_key_wrap_ad(const char *fname) { FILE *f; int ret = 0; char buf[15000], *pos, *pos2; u8 bin[2000], k[32], p[1024], c[1024 + 8], result[1024 + 8]; size_t bin_len, k_len = 0, p_len = 0, c_len = 0; int ok = 0; int fail; printf("NIST KW AD tests from %s\n", fname); f = fopen(fname, "r"); if (f == NULL) { printf("%s does not exist - cannot validate test vectors\n", fname); return 1; } while (fgets(buf, sizeof(buf), f)) { if (buf[0] == '#') continue; fail = 0; pos = os_strchr(buf, '='); if (pos == NULL) { if (os_strncmp(buf, "FAIL", 4) == 0) { fail = 1; goto skip_val_parse; } continue; } pos2 = pos - 1; while (pos2 >= buf && *pos2 == ' ') *pos2-- = '\0'; *pos++ = '\0'; while (*pos == ' ') *pos++ = '\0'; pos2 = os_strchr(pos, '\r'); if (!pos2) pos2 = os_strchr(pos, '\n'); if (pos2) *pos2 = '\0'; else pos2 = pos + os_strlen(pos); if (buf[0] == '[') { printf("%s = %s\n", buf, pos); continue; } if (os_strcmp(buf, "COUNT") == 0) { printf("Test %s - ", pos); continue; } bin_len = os_strlen(pos); if (bin_len > sizeof(bin) * 2) { printf("Too long binary data (%s)\n", buf); return 1; } if (bin_len & 0x01) { printf("Odd number of hexstring values (%s)\n", buf); return 1; } bin_len /= 2; if (hexstr2bin(pos, bin, bin_len) < 0) { printf("Invalid hex string '%s' (%s)\n", pos, buf); return 1; } if (os_strcmp(buf, "K") == 0) { if (bin_len > sizeof(k)) { printf("Too long K (%u)\n", (unsigned) bin_len); return 1; } os_memcpy(k, bin, bin_len); k_len = bin_len; continue; } if (os_strcmp(buf, "C") == 0) { if (bin_len > sizeof(c)) { printf("Too long C (%u)\n", (unsigned) bin_len); return 1; } os_memcpy(c, bin, bin_len); c_len = bin_len; continue; } skip_val_parse: if (!fail) { if (os_strcmp(buf, "P") != 0) { printf("Unexpected field '%s'\n", buf); continue; } if (bin_len > sizeof(p)) { printf("Too long P (%u)\n", (unsigned) bin_len); return 1; } os_memcpy(p, bin, bin_len); p_len = bin_len; if (p_len % 8 != 0 || c_len % 8 != 0 || c_len - p_len != 8) { printf("invalid parameter length (p_len=%u c_len=%u)\n", (unsigned) p_len, (unsigned) c_len); continue; } } if (aes_unwrap(k, k_len, (c_len / 8) - 1, c, result)) { if (fail) { printf("OK (fail reported)\n"); ok++; continue; } printf("aes_unwrap() failed\n"); ret++; continue; } if (fail) { printf("FAIL (mismatch not reported)\n"); ret++; } else if (os_memcmp(p, result, p_len) == 0) { printf("OK\n"); ok++; } else { printf("FAIL\n"); ret++; } } fclose(f); if (ret) printf("Test case failed\n"); else printf("%d test vectors OK\n", ok); return ret; }
/** * cckm_egtk_to_gtk - Calculate GTK from Encrypted GTK * @cckm_rn: Association Request Numner * @gtk: Length of BTK * @gtk_len: Length of GTK * * GTK = RC4(RN | PTK-802.1X-Encrypt-Key, EGTK) * GTK = AES-Keywrap(PTK-802.1X-Encrypt-Key, EGTK) * - where PTK-802.1X-Encrypt-Key is the key as defined in Section 0 * - Note that while the IV is not transmitted in the clear, its encrypted * value is included in the EGTK. Thus, the EGTK length shall be the GTK * key length plus 8 octets (e.g. the IV length). More explicitly, if the * broadcast cipher is TKIP, while the GTK is 32 octets, the EGTK shall * be 40 octets; similarly for AESCCMP, the GTK is 16 octets while the * EGTK shall be 24 octets. */ static int cckm_install_gtk(struct wpa_sm *sm, u32 cckm_rn, u8 *gtk, int gtk_len, int keyidx, const u8 *key_rsc, int key_rsc_len) { u8 gtk_buf[32]; enum wpa_alg alg; switch (sm->group_cipher) { case WPA_CIPHER_CCMP: alg = WPA_ALG_CCMP; break; case WPA_CIPHER_TKIP: alg = WPA_ALG_TKIP; break; case WPA_CIPHER_NONE: wpa_printf(MSG_DEBUG, "WPA: Pairwise Cipher Suite: " "NONE - do not use pairwise keys"); return 0; default: wpa_printf(MSG_WARNING, "WPA: Unsupported pairwise cipher %d", sm->pairwise_cipher); return -1; } if (sm->group_cipher == WPA_CIPHER_CCMP) { gtk_len -= 8; if (aes_unwrap(sm->ptk.kek, gtk_len / 8, gtk, gtk_buf)) { wpa_printf(MSG_WARNING, "WPA: AES unwrap " "failed - could not decrypt GTK"); return -1; } gtk = gtk_buf; } else if (sm->group_cipher == WPA_CIPHER_TKIP) { u8 data[20]; WPA_PUT_LE32(data, cckm_rn); os_memcpy(data + 4, &sm->ptk.kek, sizeof(sm->ptk.kek)); wpa_hexdump_key(MSG_DEBUG, "EGTK-Data", data, sizeof(data)); rc4_skip(data, sizeof(data), 256, gtk, gtk_len); /* Swap Tx/Rx keys for Michael MIC */ os_memcpy(gtk_buf, gtk, 16); os_memcpy(gtk_buf + 16, gtk + 24, 8); os_memcpy(gtk_buf + 24, gtk + 16, 8); gtk = gtk_buf; } wpa_hexdump_key(MSG_DEBUG, "WPA: Group Key", gtk, gtk_len); wpa_printf(MSG_DEBUG, "WPA: Installing GTK to the driver " "(keyidx=%d tx=%d len=%d).", keyidx, 0, gtk_len); wpa_hexdump(MSG_DEBUG, "WPA: RSC", key_rsc, key_rsc_len); if (wpa_sm_set_key(sm, alg, (u8 *) "\xff\xff\xff\xff\xff\xff", keyidx, 0, key_rsc, key_rsc_len, gtk, gtk_len) < 0) { wpa_printf(MSG_WARNING, "WPA: Failed to set GTK to " "the driver."); return -1; } return 0; }
int yacl_aes_unwrap(const uint8_t *kek, size_t kek_len, const uint8_t *cipher, uint8_t *plain) { return aes_unwrap(kek, kek_len, 4, cipher, plain); }