void p2p_channels_remove_freqs(struct p2p_channels *chan, const struct wpa_freq_range_list *list) { size_t o, c; if (list == NULL) return; o = 0; while (o < chan->reg_classes) { struct p2p_reg_class *op = &chan->reg_class[o]; c = 0; while (c < op->channels) { int freq = p2p_channel_to_freq(op->reg_class, op->channel[c]); if (freq > 0 && freq_range_list_includes(list, freq)) { op->channels--; os_memmove(&op->channel[c], &op->channel[c + 1], op->channels - c); } else c++; } if (op->channels == 0) { chan->reg_classes--; os_memmove(&chan->reg_class[o], &chan->reg_class[o + 1], (chan->reg_classes - o) * sizeof(struct p2p_reg_class)); } else o++; } }
unsigned char btchip_decode_base58(unsigned char WIDE *in, unsigned char length, unsigned char *out, unsigned char maxoutlen) { unsigned char tmp[164]; unsigned char buffer[164]; unsigned char i; unsigned char j; unsigned char startAt; unsigned char zeroCount = 0; if (length > sizeof(tmp)) { THROW(INVALID_PARAMETER); } os_memmove(tmp, in, length); L_DEBUG_BUF(("To decode\n", tmp, length)); for (i = 0; i < length; i++) { if (in[i] > 128) { THROW(EXCEPTION); } tmp[i] = BASE58TABLE[in[i]]; if (tmp[i] == 0xff) { THROW(EXCEPTION); } } while ((zeroCount < length) && (tmp[zeroCount] == 0)) { ++zeroCount; } j = length; startAt = zeroCount; while (startAt < length) { unsigned short remainder = 0; unsigned char divLoop; for (divLoop = startAt; divLoop < length; divLoop++) { unsigned short digit256 = (unsigned short)(tmp[divLoop] & 0xff); unsigned short tmpDiv = remainder * 58 + digit256; tmp[divLoop] = (unsigned char)(tmpDiv / 256); remainder = (tmpDiv % 256); } if (tmp[startAt] == 0) { ++startAt; } buffer[--j] = (unsigned char)remainder; } while ((j < length) && (buffer[j] == 0)) { ++j; } length = length - (j - zeroCount); if (maxoutlen < length) { L_DEBUG_APP(("Decode overflow %d %d\n", length, maxoutlen)); THROW(EXCEPTION_OVERFLOW); } os_memmove(out, buffer + j - zeroCount, length); L_DEBUG_BUF(("Decoded\n", out, length)); return length; }
unsigned char btchip_encode_base58(unsigned char WIDE *in, unsigned char length, unsigned char *out, unsigned char maxoutlen) { unsigned char tmp[164]; unsigned char buffer[164]; unsigned char j; unsigned char startAt; unsigned char zeroCount = 0; if (length > sizeof(tmp)) { THROW(INVALID_PARAMETER); } os_memmove(tmp, in, length); L_DEBUG_APP(("Length to encode %d\n", length)); L_DEBUG_BUF(("To encode\n", tmp, length)); while ((zeroCount < length) && (tmp[zeroCount] == 0)) { ++zeroCount; } j = 2 * length; startAt = zeroCount; while (startAt < length) { unsigned short remainder = 0; unsigned char divLoop; for (divLoop = startAt; divLoop < length; divLoop++) { unsigned short digit256 = (unsigned short)(tmp[divLoop] & 0xff); unsigned short tmpDiv = remainder * 256 + digit256; tmp[divLoop] = (unsigned char)(tmpDiv / 58); remainder = (tmpDiv % 58); } if (tmp[startAt] == 0) { ++startAt; } buffer[--j] = (unsigned char)BASE58ALPHABET[remainder]; } while ((j < (2 * length)) && (buffer[j] == BASE58ALPHABET[0])) { ++j; } while (zeroCount-- > 0) { buffer[--j] = BASE58ALPHABET[0]; } length = 2 * length - j; if (maxoutlen < length) { L_DEBUG_APP(("Encode overflow %d %d\n", length, maxoutlen)); THROW(EXCEPTION_OVERFLOW); } os_memmove(out, (buffer + j), length); L_DEBUG_APP(("Length encoded %d\n", length)); L_DEBUG_BUF(("Encoded\n", out, length)); return length; }
static void eloop_sock_table_remove_sock(struct eloop_sock_table *table, int sock) { int i; if (table == NULL || table->table == NULL || table->count == 0) return; for (i = 0; i < table->count; i++) { if (table->table[i].sock == sock) break; } if (i == table->count) return; eloop_trace_sock_remove_ref(table); if (i != table->count - 1) { os_memmove(&table->table[i], &table->table[i + 1], (table->count - i - 1) * sizeof(struct eloop_sock)); } table->count--; eloop.count--; table->changed = 1; eloop_trace_sock_add_ref(table); }
/** * encrypt_pw_block_with_password_hash - EncryptPwBlockWithPasswordHash() - RFC 2759, Sect. 8.10 * @password: 0-to-256-unicode-char Password (IN; UTF-8) * @password_len: Length of password * @password_hash: 16-octet PasswordHash (IN) * @pw_block: 516-byte PwBlock (OUT) * Returns: 0 on success, -1 on failure */ int encrypt_pw_block_with_password_hash( const u8 *password, size_t password_len, const u8 *password_hash, u8 *pw_block) { size_t ucs2_len, offset; u8 *pos; os_memset(pw_block, 0, PWBLOCK_LEN); if (utf8_to_ucs2(password, password_len, pw_block, 512, &ucs2_len) < 0) return -1; if (ucs2_len > 256) return -1; offset = (256 - ucs2_len) * 2; if (offset != 0) { os_memmove(pw_block + offset, pw_block, ucs2_len * 2); if (os_get_random(pw_block, offset) < 0) return -1; } /* * PasswordLength is 4 octets, but since the maximum password length is * 256, only first two (in little endian byte order) can be non-zero. */ pos = &pw_block[2 * 256]; WPA_PUT_LE16(pos, password_len * 2); rc4_skip(password_hash, 16, 0, pw_block, PWBLOCK_LEN); return 0; }
void eloop_unregister_read_sock(int sock) { size_t i; if (eloop.readers == NULL || eloop.reader_count == 0) return; for (i = 0; i < eloop.reader_count; i++) { if (eloop.readers[i].sock == sock) break; } if (i == eloop.reader_count) return; WSAEventSelect(eloop.readers[i].sock, eloop.readers[i].event, 0); WSACloseEvent(eloop.readers[i].event); if (i != eloop.reader_count - 1) { os_memmove(&eloop.readers[i], &eloop.readers[i + 1], (eloop.reader_count - i - 1) * sizeof(struct eloop_sock)); } eloop.reader_count--; eloop.reader_table_changed = 1; }
int pkcs1_v15_private_key_decrypt(struct crypto_rsa_key *key, const u8 *in, size_t inlen, u8 *out, size_t *outlen) { int res; u8 *pos, *end; res = crypto_rsa_exptmod(in, inlen, out, outlen, key, 1); if (res) return res; if (*outlen < 2 || out[0] != 0 || out[1] != 2) return -1; /* Skip PS (pseudorandom non-zero octets) */ pos = out + 2; end = out + *outlen; while (*pos && pos < end) pos++; if (pos == end) return -1; pos++; *outlen -= pos - out; /* Strip PKCS #1 header */ os_memmove(out, pos, *outlen); return 0; }
//! removes an Entry from map... void TMap_Remove(TMap * me, void * key) { void * foundElem; BYTE * pToKey; int iPos; int memsize; foundElem = TMap_Find(me, key); if (!foundElem) return; //???? not in map!!! //one less me->curCountElements--; //pointer to key is sizelenkey before... pToKey = ((BYTE*)foundElem) - me->size_Of_Key; //calc the current position iPos = (pToKey - me->mapfield) / (me->size_Of_Key+ me->size_Of_Value); memsize = (me->curCountElements - iPos) * (me->size_Of_Key+ me->size_Of_Value); //copy all memory above to the current pos... os_memmove(pToKey, pToKey + me->size_Of_Key + me->size_Of_Value, memsize ); }
static void eloop_sock_table_remove_sock(struct eloop_sock_table *table, int sock) { int i; if (table == NULL || table->table == NULL || table->count == 0) return; for (i = 0; i < table->count; i++) { if (table->table[i].sock == sock) break; } if (i == table->count) return; eloop_trace_sock_remove_ref(table); if (i != table->count - 1) { os_memmove(&table->table[i], &table->table[i + 1], (table->count - i - 1) * sizeof(struct eloop_sock)); } table->count--; eloop.count--; #ifndef CONFIG_ELOOP_EPOLL table->changed = 1; #endif /* CONFIG_ELOOP_EPOLL */ eloop_trace_sock_add_ref(table); #ifdef CONFIG_ELOOP_EPOLL if (epoll_ctl(eloop.epollfd, EPOLL_CTL_DEL, sock, NULL) < 0) { wpa_printf(MSG_ERROR, "%s: epoll_ctl(DEL) for fd=%d " "failed. %s\n", __func__, sock, strerror(errno)); return; } os_memset(&eloop.epoll_table[sock], 0, sizeof(struct eloop_sock)); #endif /* CONFIG_ELOOP_EPOLL */ }
static void wpa_bss_remove(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, const char *reason) { if (wpa_s->last_scan_res) { unsigned int i; for (i = 0; i < wpa_s->last_scan_res_used; i++) { if (wpa_s->last_scan_res[i] == bss) { os_memmove(&wpa_s->last_scan_res[i], &wpa_s->last_scan_res[i + 1], (wpa_s->last_scan_res_used - i - 1) * sizeof(struct wpa_bss *)); wpa_s->last_scan_res_used--; break; } } } wpa_bss_update_pending_connect(wpa_s, bss, NULL); dl_list_del(&bss->list); dl_list_del(&bss->list_id); wpa_s->num_bss--; wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Remove id %u BSSID " MACSTR " SSID '%s' due to %s", bss->id, MAC2STR(bss->bssid), wpa_ssid_txt(bss->ssid, bss->ssid_len), reason); wpas_notify_bss_removed(wpa_s, bss->bssid, bss->id); wpa_bss_anqp_free(bss->anqp); os_free(bss); }
u8 * eap_fast_derive_key(void *ssl_ctx, struct tls_connection *conn, const char *label, size_t len) { struct tls_keys keys; u8 *rnd = NULL, *out; int block_size; block_size = tls_connection_get_keyblock_size(ssl_ctx, conn); if (block_size < 0) return NULL; out = os_malloc(block_size + len); if (out == NULL) return NULL; if (tls_connection_prf(ssl_ctx, conn, label, 1, out, block_size + len) == 0) { os_memmove(out, out + block_size, len); return out; } if (tls_connection_get_keys(ssl_ctx, conn, &keys)) goto fail; rnd = os_malloc(keys.client_random_len + keys.server_random_len); if (rnd == NULL) goto fail; os_memcpy(rnd, keys.server_random, keys.server_random_len); os_memcpy(rnd + keys.server_random_len, keys.client_random, keys.client_random_len); wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: master_secret for key " "expansion", keys.master_key, keys.master_key_len); if (tls_prf(keys.master_key, keys.master_key_len, label, rnd, keys.client_random_len + keys.server_random_len, out, block_size + len)) goto fail; os_free(rnd); os_memmove(out, out + block_size, len); return out; fail: os_free(rnd); os_free(out); return NULL; }
static void l2_packet_receive(int sock, void *eloop_ctx, void *sock_ctx) { struct l2_packet_data *l2 = eloop_ctx; u8 buf[2300]; int res; #ifdef WAPI struct l2_ethhdr l2_hdr; struct wpa_supplicant *wpa_s = (struct wpa_supplicant *)l2->rx_callback_ctx; struct l2_packet_data *l2_wapi = wpa_s->l2_wapi; int is_wapi = 0; #endif struct sockaddr_ll ll; socklen_t fromlen; #ifdef WAPI wpa_printf(MSG_DEBUG, "%s: l2=%p, wpa_s->l2_wapi=%p\n", __FUNCTION__, l2, l2_wapi); if (l2 == l2_wapi) { is_wapi = 1; os_memset(&l2_hdr, 0, sizeof(l2_hdr)); res = recvfrom(sock, buf, sizeof(buf), 0, NULL, NULL); } else { #endif os_memset(&ll, 0, sizeof(ll)); fromlen = sizeof(ll); res = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *) &ll, &fromlen); #ifdef WAPI } #endif if (res < 0) { wpa_printf(MSG_DEBUG, "l2_packet_receive - recvfrom: %s", strerror(errno)); return; } #ifdef WAPI if (is_wapi) { os_memcpy(&l2_hdr, buf, ETH_HLEN); l2_hdr.h_proto = ntohs (l2_hdr.h_proto); res -= ETH_HLEN; if (res > 0) os_memmove(buf, (char *)buf + ETH_HLEN, res); else res = 0; l2->rx_callback(l2->rx_callback_ctx, l2_hdr.h_source, buf, res); } else { #endif l2->rx_callback(l2->rx_callback_ctx, ll.sll_addr, buf, res); #ifdef WAPI } #endif }
//***************************************************************************** // remove one char at cursor static void ICACHE_FLASH_ATTR microrl_backspace (microrl_t * pThis) { if (pThis->cursor > 0) { terminal_backspace (pThis); os_memmove (pThis->cmdline + pThis->cursor-1, pThis->cmdline + pThis->cursor, pThis->cmdlen-pThis->cursor+1); pThis->cursor--; pThis->cmdline [pThis->cmdlen] = '\0'; pThis->cmdlen--; } }
int crypto_public_key_decrypt_pkcs1(struct crypto_public_key *key, const u8 *crypt, size_t crypt_len, u8 *plain, size_t *plain_len) { size_t len; u8 *pos; len = *plain_len; if (crypto_rsa_exptmod(crypt, crypt_len, plain, &len, (struct crypto_rsa_key *) key, 0) < 0) return -1; /* * PKCS #1 v1.5, 8.1: * * EB = 00 || BT || PS || 00 || D * BT = 01 * PS = k-3-||D|| times FF * k = length of modulus in octets */ if (len < 3 + 8 + 16 /* min hash len */ || plain[0] != 0x00 || plain[1] != 0x01 || plain[2] != 0xff) { wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB " "structure"); return -1; } pos = plain + 3; while (pos < plain + len && *pos == 0xff) pos++; if (pos - plain - 2 < 8) { /* PKCS #1 v1.5, 8.1: At least eight octets long PS */ wpa_printf(MSG_INFO, "LibTomCrypt: Too short signature " "padding"); return -1; } if (pos + 16 /* min hash len */ >= plain + len || *pos != 0x00) { wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB " "structure (2)"); return -1; } pos++; len -= pos - plain; /* Strip PKCS #1 header */ os_memmove(plain, pos, len); *plain_len = len; return 0; }
/** * eap_sm_process_nak - Process EAP-Response/Nak * @sm: Pointer to EAP state machine allocated with eap_server_sm_init() * @nak_list: Nak list (allowed methods) from the supplicant * @len: Length of nak_list in bytes * * This function is called when EAP-Response/Nak is received from the * supplicant. This can happen for both phase 1 and phase 2 authentications. */ void eap_sm_process_nak(struct eap_sm *sm, const u8 *nak_list, size_t len) { int i; size_t j; if (sm->user == NULL) return; wpa_printf(MSG_MSGDUMP, "EAP: processing NAK (current EAP method " "index %d)", sm->user_eap_method_index); wpa_hexdump(MSG_MSGDUMP, "EAP: configured methods", (u8 *) sm->user->methods, EAP_MAX_METHODS * sizeof(sm->user->methods[0])); wpa_hexdump(MSG_MSGDUMP, "EAP: list of methods supported by the peer", nak_list, len); i = sm->user_eap_method_index; while (i < EAP_MAX_METHODS && (sm->user->methods[i].vendor != EAP_VENDOR_IETF || sm->user->methods[i].method != EAP_TYPE_NONE)) { if (sm->user->methods[i].vendor != EAP_VENDOR_IETF) goto not_found; for (j = 0; j < len; j++) { if (nak_list[j] == sm->user->methods[i].method) { break; } } if (j < len) { /* found */ i++; continue; } not_found: /* not found - remove from the list */ if (i + 1 < EAP_MAX_METHODS) { os_memmove(&sm->user->methods[i], &sm->user->methods[i + 1], (EAP_MAX_METHODS - i - 1) * sizeof(sm->user->methods[0])); } sm->user->methods[EAP_MAX_METHODS - 1].vendor = EAP_VENDOR_IETF; sm->user->methods[EAP_MAX_METHODS - 1].method = EAP_TYPE_NONE; } wpa_hexdump(MSG_MSGDUMP, "EAP: new list of configured methods", (u8 *) sm->user->methods, EAP_MAX_METHODS * sizeof(sm->user->methods[0])); }
int eap_eke_shared_secret(struct eap_eke_session *sess, const u8 *key, const u8 *dhpriv, const u8 *peer_dhcomp) { u8 zeros[EAP_EKE_MAX_HASH_LEN]; u8 peer_pub[EAP_EKE_MAX_DH_LEN]; u8 modexp[EAP_EKE_MAX_DH_LEN]; size_t len; const struct dh_group *dh; dh = eap_eke_dh_group(sess->dhgroup); if (sess->encr != EAP_EKE_ENCR_AES128_CBC || !dh) return -1; /* Decrypt peer DHComponent */ os_memcpy(peer_pub, peer_dhcomp + AES_BLOCK_SIZE, dh->prime_len); if (aes_128_cbc_decrypt(key, peer_dhcomp, peer_pub, dh->prime_len) < 0) { wpa_printf(MSG_INFO, "EAP-EKE: Failed to decrypt DHComponent"); return -1; } wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Decrypted peer DH pubkey", peer_pub, dh->prime_len); /* SharedSecret = prf(0+, g ^ (x_s * x_p) (mod p)) */ len = dh->prime_len; if (crypto_dh_derive_secret(*dh->generator, dh->prime, dh->prime_len, NULL, 0, dhpriv, dh->prime_len, peer_pub, dh->prime_len, modexp, &len) < 0) return -1; if (len < dh->prime_len) { size_t pad = dh->prime_len - len; os_memmove(modexp + pad, modexp, len); os_memset(modexp, 0, pad); } os_memset(zeros, 0, sess->auth_len); if (eap_eke_prf(sess->prf, zeros, sess->auth_len, modexp, dh->prime_len, NULL, 0, sess->shared_secret) < 0) return -1; wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: SharedSecret", sess->shared_secret, sess->auth_len); return 0; }
//***************************************************************************** // insert len char of text at cursor position static int ICACHE_FLASH_ATTR microrl_insert_text (microrl_t * pThis, char * text, int len) { int i; if (pThis->cmdlen + len < _COMMAND_LINE_LEN) { os_memmove (pThis->cmdline + pThis->cursor + len, pThis->cmdline + pThis->cursor, pThis->cmdlen - pThis->cursor); for (i = 0; i < len; i++) { pThis->cmdline [pThis->cursor + i] = text [i]; // if (pThis->cmdline [pThis->cursor + i] == ' ') { // pThis->cmdline [pThis->cursor + i] = 0; // } } pThis->cursor += len; pThis->cmdlen += len; pThis->cmdline [pThis->cmdlen] = '\0'; return true; } return false; }
/* * Assumptions: * > fromaddr is INTERNAL_FLASH_READ_UNIT_SIZE aligned * > size is a multiple of INTERNAL_FLASH_READ_UNIT_SIZE */ uint32_t platform_s_flash_read( void *to, uint32_t fromaddr, uint32_t size ) { if (size==0) return 0; SpiFlashOpResult r; system_soft_wdt_feed (); const uint32_t blkmask = (INTERNAL_FLASH_READ_UNIT_SIZE - 1); if( ((uint32_t)to) & blkmask ) { uint32_t size2=size-INTERNAL_FLASH_READ_UNIT_SIZE; uint32* to2=(uint32*)((((uint32_t)to)&(~blkmask))+INTERNAL_FLASH_READ_UNIT_SIZE); r = flash_read(fromaddr, to2, size2); if(SPI_FLASH_RESULT_OK == r) { os_memmove(to,to2,size2); char back[ INTERNAL_FLASH_READ_UNIT_SIZE ] __attribute__ ((aligned(INTERNAL_FLASH_READ_UNIT_SIZE))); r=flash_read(fromaddr+size2,(uint32*)back,INTERNAL_FLASH_READ_UNIT_SIZE); os_memcpy((uint8_t*)to+size2,back,INTERNAL_FLASH_READ_UNIT_SIZE); }
/** * wpa_config_add_prio_network - Add a network to priority lists * @config: Configuration data from wpa_config_read() * @ssid: Pointer to the network configuration to be added to the list * Returns: 0 on success, -1 on failure * * This function is used to add a network block to the priority list of * networks. This must be called for each network when reading in the full * configuration. In addition, this can be used indirectly when updating * priorities by calling wpa_config_update_prio_list(). */ int wpa_config_add_prio_network(struct wpa_config *config, struct wpa_ssid *ssid) { int prio; struct wpa_ssid *prev, **nlist; /* * Add to an existing priority list if one is available for the * configured priority level for this network. */ for (prio = 0; prio < config->num_prio; prio++) { prev = config->pssid[prio]; if (prev->priority == ssid->priority) { while (prev->pnext) prev = prev->pnext; prev->pnext = ssid; return 0; } } /* First network for this priority - add a new priority list */ nlist = os_realloc(config->pssid, (config->num_prio + 1) * sizeof(struct wpa_ssid *)); if (nlist == NULL) return -1; for (prio = 0; prio < config->num_prio; prio++) { if (nlist[prio]->priority < ssid->priority) break; } os_memmove(&nlist[prio + 1], &nlist[prio], (config->num_prio - prio) * sizeof(struct wpa_ssid *)); nlist[prio] = ssid; config->num_prio++; config->pssid = nlist; return 0; }
ICACHE_FLASH_ATTR void url_decode(char *s) { size_t l, i; char *p; uint8_t f; l = os_strlen(s) + 1; while (1) { f = 0; for (i=0; i<MAP_LEN; i++) { if ((p = strstr(s, map[i][0])) != NULL) { *p = map[i][1][0]; os_memmove(p+1, p+3, l - ((p+3)-s)); l -= 2; f = 1; } } if (f == 0) break; } }
void eloop_unregister_event(void *event, size_t event_size) { size_t i; HANDLE h = event; if (eloop.events == NULL || eloop.event_count == 0 || event_size != sizeof(HANDLE)) return; for (i = 0; i < eloop.event_count; i++) { if (eloop.events[i].event == h) break; } if (i == eloop.event_count) return; if (i != eloop.event_count - 1) { os_memmove(&eloop.events[i], &eloop.events[i + 1], (eloop.event_count - i - 1) * sizeof(struct eloop_event)); } eloop.event_count--; }
void u2f_io_send(uint8_t *buffer, uint16_t length, u2f_transport_media_t media) { if (media == U2F_MEDIA_USB) { os_memset(u2fSegment, 0, sizeof(u2fSegment)); } os_memmove(u2fSegment, buffer, length); // PRINTF("u2f_io_send\n"); if (u2fFirstCommand) { u2fFirstCommand = 0; } switch (media) { case U2F_MEDIA_USB: io_usb_send_apdu_data(u2fSegment, USB_SEGMENT_SIZE); break; #ifdef HAVE_BLE case U2F_MEDIA_BLE: BLE_protocol_send(buffer, length); break; #endif default: PRINTF("Request to send on unsupported media %d\n", media); break; } }
void sme_authenticate(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, struct wpa_ssid *ssid) { struct wpa_driver_auth_params params; struct wpa_ssid *old_ssid; #ifdef CONFIG_IEEE80211R const u8 *ie; #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_IEEE80211R const u8 *md = NULL; #endif /* CONFIG_IEEE80211R */ int i, bssid_changed; #if defined(ANDROID_P2P) && defined(WIFI_EAGLE) int freq = 0; #endif /* ANDROID_P2P && WIFI_EAGLE */ if (bss == NULL) { wpa_msg(wpa_s, MSG_ERROR, "SME: No scan result available for " "the network"); return; } wpa_s->current_bss = bss; os_memset(¶ms, 0, sizeof(params)); wpa_s->reassociate = 0; params.freq = bss->freq; params.bssid = bss->bssid; params.ssid = bss->ssid; params.ssid_len = bss->ssid_len; params.p2p = ssid->p2p_group; if (wpa_s->sme.ssid_len != params.ssid_len || os_memcmp(wpa_s->sme.ssid, params.ssid, params.ssid_len) != 0) wpa_s->sme.prev_bssid_set = 0; wpa_s->sme.freq = params.freq; os_memcpy(wpa_s->sme.ssid, params.ssid, params.ssid_len); wpa_s->sme.ssid_len = params.ssid_len; params.auth_alg = WPA_AUTH_ALG_OPEN; #ifdef IEEE8021X_EAPOL if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) { if (ssid->leap) { if (ssid->non_leap == 0) params.auth_alg = WPA_AUTH_ALG_LEAP; else params.auth_alg |= WPA_AUTH_ALG_LEAP; } } #endif /* IEEE8021X_EAPOL */ wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", params.auth_alg); if (ssid->auth_alg) { params.auth_alg = ssid->auth_alg; wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: " "0x%x", params.auth_alg); } for (i = 0; i < NUM_WEP_KEYS; i++) { if (ssid->wep_key_len[i]) params.wep_key[i] = ssid->wep_key[i]; params.wep_key_len[i] = ssid->wep_key_len[i]; } params.wep_tx_keyidx = ssid->wep_tx_keyidx; bssid_changed = !is_zero_ether_addr(wpa_s->bssid); os_memset(wpa_s->bssid, 0, ETH_ALEN); os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN); if (bssid_changed) wpas_notify_bssid_changed(wpa_s); if ((wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) || wpa_bss_get_ie(bss, WLAN_EID_RSN)) && wpa_key_mgmt_wpa(ssid->key_mgmt)) { int try_opportunistic; try_opportunistic = ssid->proactive_key_caching && (ssid->proto & WPA_PROTO_RSN); if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid, wpa_s->current_ssid, try_opportunistic) == 0) eapol_sm_notify_pmkid_attempt(wpa_s->eapol, 1); wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie); if (wpa_supplicant_set_suites(wpa_s, bss, ssid, wpa_s->sme.assoc_req_ie, &wpa_s->sme.assoc_req_ie_len)) { wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA " "key management and encryption suites"); return; } } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) { /* * Both WPA and non-WPA IEEE 802.1X enabled in configuration - * use non-WPA since the scan results did not indicate that the * AP is using WPA or WPA2. */ wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); wpa_s->sme.assoc_req_ie_len = 0; } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) { wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie); if (wpa_supplicant_set_suites(wpa_s, NULL, ssid, wpa_s->sme.assoc_req_ie, &wpa_s->sme.assoc_req_ie_len)) { wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA " "key management and encryption suites (no " "scan results)"); return; } #ifdef CONFIG_WPS } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) { struct wpabuf *wps_ie; wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid)); if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_s->sme.assoc_req_ie)) { wpa_s->sme.assoc_req_ie_len = wpabuf_len(wps_ie); os_memcpy(wpa_s->sme.assoc_req_ie, wpabuf_head(wps_ie), wpa_s->sme.assoc_req_ie_len); } else wpa_s->sme.assoc_req_ie_len = 0; wpabuf_free(wps_ie); wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); #endif /* CONFIG_WPS */ } else { wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); wpa_s->sme.assoc_req_ie_len = 0; } #ifdef CONFIG_IEEE80211R ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN); if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN) md = ie + 2; wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0); if (md) { /* Prepare for the next transition */ wpa_ft_prepare_auth_request(wpa_s->wpa, ie); } if (md && wpa_key_mgmt_ft(ssid->key_mgmt)) { if (wpa_s->sme.assoc_req_ie_len + 5 < sizeof(wpa_s->sme.assoc_req_ie)) { struct rsn_mdie *mdie; u8 *pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len; *pos++ = WLAN_EID_MOBILITY_DOMAIN; *pos++ = sizeof(*mdie); mdie = (struct rsn_mdie *) pos; os_memcpy(mdie->mobility_domain, md, MOBILITY_DOMAIN_ID_LEN); mdie->ft_capab = md[MOBILITY_DOMAIN_ID_LEN]; wpa_s->sme.assoc_req_ie_len += 5; } if (wpa_s->sme.ft_used && os_memcmp(md, wpa_s->sme.mobility_domain, 2) == 0 && wpa_sm_has_ptk(wpa_s->wpa)) { wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying to use FT " "over-the-air"); params.auth_alg = WPA_AUTH_ALG_FT; params.ie = wpa_s->sme.ft_ies; params.ie_len = wpa_s->sme.ft_ies_len; } } #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_IEEE80211W wpa_s->sme.mfp = ssid->ieee80211w; if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION) { const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN); struct wpa_ie_data _ie; if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &_ie) == 0 && _ie.capabilities & (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) { wpa_dbg(wpa_s, MSG_DEBUG, "SME: Selected AP supports " "MFP: require MFP"); wpa_s->sme.mfp = MGMT_FRAME_PROTECTION_REQUIRED; } } #endif /* CONFIG_IEEE80211W */ #ifdef CONFIG_P2P if (wpa_s->global->p2p) { u8 *pos; size_t len; int res; pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len; len = sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len; res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len, ssid->p2p_group); if (res >= 0) wpa_s->sme.assoc_req_ie_len += res; } #endif /* CONFIG_P2P */ #ifdef CONFIG_HS20 if (wpa_s->conf->hs20) { struct wpabuf *hs20; hs20 = wpabuf_alloc(20); if (hs20) { wpas_hs20_add_indication(hs20); os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len, wpabuf_head(hs20), wpabuf_len(hs20)); wpa_s->sme.assoc_req_ie_len += wpabuf_len(hs20); wpabuf_free(hs20); } } #endif /* CONFIG_HS20 */ #ifdef CONFIG_INTERWORKING if (wpa_s->conf->interworking) { u8 *pos = wpa_s->sme.assoc_req_ie; if (wpa_s->sme.assoc_req_ie_len > 0 && pos[0] == WLAN_EID_RSN) pos += 2 + pos[1]; os_memmove(pos + 6, pos, wpa_s->sme.assoc_req_ie_len - (pos - wpa_s->sme.assoc_req_ie)); wpa_s->sme.assoc_req_ie_len += 6; *pos++ = WLAN_EID_EXT_CAPAB; *pos++ = 4; *pos++ = 0x00; *pos++ = 0x00; *pos++ = 0x00; *pos++ = 0x80; /* Bit 31 - Interworking */ } #endif /* CONFIG_INTERWORKING */ wpa_supplicant_cancel_sched_scan(wpa_s); wpa_supplicant_cancel_scan(wpa_s); wpa_msg(wpa_s, MSG_INFO, "SME: Trying to authenticate with " MACSTR " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid), wpa_ssid_txt(params.ssid, params.ssid_len), params.freq); wpa_clear_keys(wpa_s, bss->bssid); wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING); old_ssid = wpa_s->current_ssid; wpa_s->current_ssid = ssid; wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid); wpa_supplicant_initiate_eapol(wpa_s); if (old_ssid != wpa_s->current_ssid) wpas_notify_network_changed(wpa_s); wpa_s->sme.auth_alg = params.auth_alg; #if defined(ANDROID_P2P) && defined(WIFI_EAGLE) /* If multichannel concurrency is not supported, check for any frequency * conflict and take appropriate action. */ wpa_printf(MSG_DEBUG, "%s EAGLE: Priority choose", __func__); if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MULTI_CHANNEL_CONCURRENT) && ((freq = wpa_drv_shared_freq(wpa_s)) > 0) && (freq != params.freq)) { wpa_printf(MSG_DEBUG, "Shared interface with conflicting frequency found (%d != %d)" , freq, params.freq); if (wpas_p2p_handle_frequency_conflicts(wpa_s, params.freq) < 0) { /* Handling conflicts failed. Disable the current connect req and * notify the userspace to take appropriate action */ wpa_printf(MSG_DEBUG, "proiritize is not set. Notifying user space to handle the case"); wpa_supplicant_disable_network(wpa_s, ssid); wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_FREQ_CONFLICT " id=%d", ssid->id); os_memset(wpa_s->pending_bssid, 0, ETH_ALEN); return; } } #endif /* ANDROID_P2P && WIFI_EAGLE */ if (wpa_drv_authenticate(wpa_s, ¶ms) < 0) { wpa_msg(wpa_s, MSG_INFO, "SME: Authentication request to the " "driver failed"); wpas_connection_failed(wpa_s, bss->bssid); wpa_supplicant_mark_disassoc(wpa_s); return; } eloop_register_timeout(SME_AUTH_TIMEOUT, 0, sme_auth_timer, wpa_s, NULL); /* * Association will be started based on the authentication event from * the driver. */ }
void sme_authenticate(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, struct wpa_ssid *ssid) { struct wpa_driver_auth_params params; struct wpa_ssid *old_ssid; #ifdef CONFIG_IEEE80211R const u8 *ie; #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_IEEE80211R const u8 *md = NULL; #endif /* CONFIG_IEEE80211R */ int i, bssid_changed; if (bss == NULL) { wpa_msg(wpa_s, MSG_ERROR, "SME: No scan result available for " "the network"); return; } wpa_s->current_bss = bss; os_memset(¶ms, 0, sizeof(params)); wpa_s->reassociate = 0; params.freq = bss->freq; params.bssid = bss->bssid; params.ssid = bss->ssid; params.ssid_len = bss->ssid_len; params.p2p = ssid->p2p_group; if (wpa_s->sme.ssid_len != params.ssid_len || os_memcmp(wpa_s->sme.ssid, params.ssid, params.ssid_len) != 0) wpa_s->sme.prev_bssid_set = 0; wpa_s->sme.freq = params.freq; os_memcpy(wpa_s->sme.ssid, params.ssid, params.ssid_len); wpa_s->sme.ssid_len = params.ssid_len; params.auth_alg = WPA_AUTH_ALG_OPEN; #ifdef IEEE8021X_EAPOL if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) { if (ssid->leap) { if (ssid->non_leap == 0) params.auth_alg = WPA_AUTH_ALG_LEAP; else params.auth_alg |= WPA_AUTH_ALG_LEAP; } } #endif /* IEEE8021X_EAPOL */ wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", params.auth_alg); if (ssid->auth_alg) { params.auth_alg = ssid->auth_alg; wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: " "0x%x", params.auth_alg); } for (i = 0; i < NUM_WEP_KEYS; i++) { if (ssid->wep_key_len[i]) params.wep_key[i] = ssid->wep_key[i]; params.wep_key_len[i] = ssid->wep_key_len[i]; } params.wep_tx_keyidx = ssid->wep_tx_keyidx; bssid_changed = !is_zero_ether_addr(wpa_s->bssid); os_memset(wpa_s->bssid, 0, ETH_ALEN); os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN); if (bssid_changed) wpas_notify_bssid_changed(wpa_s); if ((wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) || wpa_bss_get_ie(bss, WLAN_EID_RSN)) && wpa_key_mgmt_wpa(ssid->key_mgmt)) { int try_opportunistic; try_opportunistic = ssid->proactive_key_caching && (ssid->proto & WPA_PROTO_RSN); if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid, wpa_s->current_ssid, try_opportunistic) == 0) eapol_sm_notify_pmkid_attempt(wpa_s->eapol, 1); wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie); if (wpa_supplicant_set_suites(wpa_s, bss, ssid, wpa_s->sme.assoc_req_ie, &wpa_s->sme.assoc_req_ie_len)) { wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA " "key management and encryption suites"); return; } } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) { wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie); if (wpa_supplicant_set_suites(wpa_s, NULL, ssid, wpa_s->sme.assoc_req_ie, &wpa_s->sme.assoc_req_ie_len)) { wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA " "key management and encryption suites (no " "scan results)"); return; } #ifdef CONFIG_WPS } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) { struct wpabuf *wps_ie; wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid)); if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_s->sme.assoc_req_ie)) { wpa_s->sme.assoc_req_ie_len = wpabuf_len(wps_ie); os_memcpy(wpa_s->sme.assoc_req_ie, wpabuf_head(wps_ie), wpa_s->sme.assoc_req_ie_len); } else wpa_s->sme.assoc_req_ie_len = 0; wpabuf_free(wps_ie); wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); #endif /* CONFIG_WPS */ } else { wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); wpa_s->sme.assoc_req_ie_len = 0; } #ifdef CONFIG_IEEE80211R ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN); if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN) md = ie + 2; wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0); if (md) { /* Prepare for the next transition */ wpa_ft_prepare_auth_request(wpa_s->wpa, ie); } if (md && wpa_key_mgmt_ft(ssid->key_mgmt)) { if (wpa_s->sme.assoc_req_ie_len + 5 < sizeof(wpa_s->sme.assoc_req_ie)) { struct rsn_mdie *mdie; u8 *pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len; *pos++ = WLAN_EID_MOBILITY_DOMAIN; *pos++ = sizeof(*mdie); mdie = (struct rsn_mdie *) pos; os_memcpy(mdie->mobility_domain, md, MOBILITY_DOMAIN_ID_LEN); mdie->ft_capab = md[MOBILITY_DOMAIN_ID_LEN]; wpa_s->sme.assoc_req_ie_len += 5; } if (wpa_s->sme.ft_used && os_memcmp(md, wpa_s->sme.mobility_domain, 2) == 0 && wpa_sm_has_ptk(wpa_s->wpa)) { wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying to use FT " "over-the-air"); params.auth_alg = WPA_AUTH_ALG_FT; params.ie = wpa_s->sme.ft_ies; params.ie_len = wpa_s->sme.ft_ies_len; } } #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_IEEE80211W wpa_s->sme.mfp = ssid->ieee80211w; if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION) { const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN); struct wpa_ie_data _ie; if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &_ie) == 0 && _ie.capabilities & (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) { wpa_dbg(wpa_s, MSG_DEBUG, "SME: Selected AP supports " "MFP: require MFP"); wpa_s->sme.mfp = MGMT_FRAME_PROTECTION_REQUIRED; } } #endif /* CONFIG_IEEE80211W */ #ifdef CONFIG_P2P if (wpa_s->global->p2p) { u8 *pos; size_t len; int res; pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len; len = sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len; res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len, ssid->p2p_group); if (res >= 0) wpa_s->sme.assoc_req_ie_len += res; } #endif /* CONFIG_P2P */ #ifdef CONFIG_INTERWORKING if (wpa_s->conf->interworking) { u8 *pos = wpa_s->sme.assoc_req_ie; if (wpa_s->sme.assoc_req_ie_len > 0 && pos[0] == WLAN_EID_RSN) pos += 2 + pos[1]; os_memmove(pos + 6, pos, wpa_s->sme.assoc_req_ie_len - (pos - wpa_s->sme.assoc_req_ie)); wpa_s->sme.assoc_req_ie_len += 6; *pos++ = WLAN_EID_EXT_CAPAB; *pos++ = 4; *pos++ = 0x00; *pos++ = 0x00; *pos++ = 0x00; *pos++ = 0x80; /* Bit 31 - Interworking */ } #endif /* CONFIG_INTERWORKING */ wpa_supplicant_cancel_sched_scan(wpa_s); wpa_supplicant_cancel_scan(wpa_s); wpa_msg(wpa_s, MSG_INFO, "SME: Trying to authenticate with " MACSTR " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid), wpa_ssid_txt(params.ssid, params.ssid_len), params.freq); wpa_clear_keys(wpa_s, bss->bssid); wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING); old_ssid = wpa_s->current_ssid; wpa_s->current_ssid = ssid; wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid); wpa_supplicant_initiate_eapol(wpa_s); if (old_ssid != wpa_s->current_ssid) wpas_notify_network_changed(wpa_s); wpa_s->sme.auth_alg = params.auth_alg; if (wpa_drv_authenticate(wpa_s, ¶ms) < 0) { wpa_msg(wpa_s, MSG_INFO, "SME: Authentication request to the " "driver failed"); wpa_supplicant_req_scan(wpa_s, 1, 0); return; } eloop_register_timeout(SME_AUTH_TIMEOUT, 0, sme_auth_timer, wpa_s, NULL); /* * Association will be started based on the authentication event from * the driver. */ }
int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid) { u8 *start, *end, *rpos, *rend; int added = 0; start = ies; end = ies + ies_len; while (start < end) { if (*start == WLAN_EID_RSN) break; start += 2 + start[1]; } if (start >= end) { wpa_printf(MSG_ERROR, "FT: Could not find RSN IE in " "IEs data"); return -1; } wpa_hexdump(MSG_DEBUG, "FT: RSN IE before modification", start, 2 + start[1]); /* Find start of PMKID-Count */ rpos = start + 2; rend = rpos + start[1]; /* Skip Version and Group Data Cipher Suite */ rpos += 2 + 4; /* Skip Pairwise Cipher Suite Count and List */ rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN; /* Skip AKM Suite Count and List */ rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN; if (rpos == rend) { /* Add RSN Capabilities */ os_memmove(rpos + 2, rpos, end - rpos); *rpos++ = 0; *rpos++ = 0; } else { /* Skip RSN Capabilities */ rpos += 2; if (rpos > rend) { wpa_printf(MSG_ERROR, "FT: Could not parse RSN IE in " "IEs data"); return -1; } } if (rpos == rend) { /* No PMKID-Count field included; add it */ os_memmove(rpos + 2 + PMKID_LEN, rpos, end - rpos); WPA_PUT_LE16(rpos, 1); rpos += 2; os_memcpy(rpos, pmkid, PMKID_LEN); added += 2 + PMKID_LEN; start[1] += 2 + PMKID_LEN; } else { /* PMKID-Count was included; use it */ if (WPA_GET_LE16(rpos) != 0) { wpa_printf(MSG_ERROR, "FT: Unexpected PMKID " "in RSN IE in EAPOL-Key data"); return -1; } WPA_PUT_LE16(rpos, 1); rpos += 2; os_memmove(rpos + PMKID_LEN, rpos, end - rpos); os_memcpy(rpos, pmkid, PMKID_LEN); added += PMKID_LEN; start[1] += PMKID_LEN; } wpa_hexdump(MSG_DEBUG, "FT: RSN IE after modification " "(PMKID inserted)", start, 2 + start[1]); return added; }
static int tls_write_server_key_exchange(struct tlsv1_server *conn, u8 **msgpos, u8 *end) { tls_key_exchange keyx; const struct tls_cipher_suite *suite; #ifdef EAP_FAST u8 *pos, *rhdr, *hs_start, *hs_length; size_t rlen; u8 *dh_ys; size_t dh_ys_len; #endif /* EAP_FAST */ suite = tls_get_cipher_suite(conn->rl.cipher_suite); if (suite == NULL) keyx = TLS_KEY_X_NULL; else keyx = suite->key_exchange; if (!tls_server_key_exchange_allowed(conn->rl.cipher_suite)) { wpa_printf(MSG_DEBUG, "TLSv1: No ServerKeyExchange needed"); return 0; } if (keyx != TLS_KEY_X_DH_anon) { /* TODO? */ wpa_printf(MSG_DEBUG, "TLSv1: ServerKeyExchange not yet " "supported with key exchange type %d", keyx); return -1; } #ifdef EAP_FAST if (conn->cred == NULL || conn->cred->dh_p == NULL || conn->cred->dh_g == NULL) { wpa_printf(MSG_DEBUG, "TLSv1: No DH parameters available for " "ServerKeyExhcange"); return -1; } os_free(conn->dh_secret); conn->dh_secret_len = conn->cred->dh_p_len; conn->dh_secret = os_malloc(conn->dh_secret_len); if (conn->dh_secret == NULL) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate " "memory for secret (Diffie-Hellman)"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } if (os_get_random(conn->dh_secret, conn->dh_secret_len)) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to get random " "data for Diffie-Hellman"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); os_free(conn->dh_secret); conn->dh_secret = NULL; return -1; } if (os_memcmp(conn->dh_secret, conn->cred->dh_p, conn->dh_secret_len) > 0) conn->dh_secret[0] = 0; /* make sure secret < p */ pos = conn->dh_secret; while (pos + 1 < conn->dh_secret + conn->dh_secret_len && *pos == 0) pos++; if (pos != conn->dh_secret) { os_memmove(conn->dh_secret, pos, conn->dh_secret_len - (pos - conn->dh_secret)); conn->dh_secret_len -= pos - conn->dh_secret; } wpa_hexdump_key(MSG_DEBUG, "TLSv1: DH server's secret value", conn->dh_secret, conn->dh_secret_len); /* Ys = g^secret mod p */ dh_ys_len = conn->cred->dh_p_len; dh_ys = os_malloc(dh_ys_len); if (dh_ys == NULL) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate memory for " "Diffie-Hellman"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } if (crypto_mod_exp(conn->cred->dh_g, conn->cred->dh_g_len, conn->dh_secret, conn->dh_secret_len, conn->cred->dh_p, conn->cred->dh_p_len, dh_ys, &dh_ys_len)) { tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); os_free(dh_ys); return -1; } wpa_hexdump(MSG_DEBUG, "TLSv1: DH Ys (server's public value)", dh_ys, dh_ys_len); /* * struct { * select (KeyExchangeAlgorithm) { * case diffie_hellman: * ServerDHParams params; * Signature signed_params; * case rsa: * ServerRSAParams params; * Signature signed_params; * }; * } ServerKeyExchange; * * struct { * opaque dh_p<1..2^16-1>; * opaque dh_g<1..2^16-1>; * opaque dh_Ys<1..2^16-1>; * } ServerDHParams; */ pos = *msgpos; wpa_printf(MSG_DEBUG, "TLSv1: Send ServerKeyExchange"); rhdr = pos; pos += TLS_RECORD_HEADER_LEN; /* opaque fragment[TLSPlaintext.length] */ /* Handshake */ hs_start = pos; /* HandshakeType msg_type */ *pos++ = TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE; /* uint24 length (to be filled) */ hs_length = pos; pos += 3; /* body - ServerDHParams */ /* dh_p */ if (pos + 2 + conn->cred->dh_p_len > end) { wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for " "dh_p"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); os_free(dh_ys); return -1; } WPA_PUT_BE16(pos, conn->cred->dh_p_len); pos += 2; os_memcpy(pos, conn->cred->dh_p, conn->cred->dh_p_len); pos += conn->cred->dh_p_len; /* dh_g */ if (pos + 2 + conn->cred->dh_g_len > end) { wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for " "dh_g"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); os_free(dh_ys); return -1; } WPA_PUT_BE16(pos, conn->cred->dh_g_len); pos += 2; os_memcpy(pos, conn->cred->dh_g, conn->cred->dh_g_len); pos += conn->cred->dh_g_len; /* dh_Ys */ if (pos + 2 + dh_ys_len > end) { wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for " "dh_Ys"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); os_free(dh_ys); return -1; } WPA_PUT_BE16(pos, dh_ys_len); pos += 2; os_memcpy(pos, dh_ys, dh_ys_len); pos += dh_ys_len; os_free(dh_ys); WPA_PUT_BE24(hs_length, pos - hs_length - 3); if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } pos = rhdr + rlen; tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); *msgpos = pos; return 0; #else /* EAP_FAST */ return -1; #endif /* EAP_FAST */ }
static void sme_send_authentication(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, struct wpa_ssid *ssid, int start) { struct wpa_driver_auth_params params; struct wpa_ssid *old_ssid; #ifdef CONFIG_IEEE80211R const u8 *ie; #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_IEEE80211R const u8 *md = NULL; #endif /* CONFIG_IEEE80211R */ int i, bssid_changed; struct wpabuf *resp = NULL; u8 ext_capab[18]; int ext_capab_len; int skip_auth; if (bss == NULL) { wpa_msg(wpa_s, MSG_ERROR, "SME: No scan result available for " "the network"); wpas_connect_work_done(wpa_s); return; } skip_auth = wpa_s->conf->reassoc_same_bss_optim && wpa_s->reassoc_same_bss; wpa_s->current_bss = bss; os_memset(¶ms, 0, sizeof(params)); wpa_s->reassociate = 0; params.freq = bss->freq; params.bssid = bss->bssid; params.ssid = bss->ssid; params.ssid_len = bss->ssid_len; params.p2p = ssid->p2p_group; if (wpa_s->sme.ssid_len != params.ssid_len || os_memcmp(wpa_s->sme.ssid, params.ssid, params.ssid_len) != 0) wpa_s->sme.prev_bssid_set = 0; wpa_s->sme.freq = params.freq; os_memcpy(wpa_s->sme.ssid, params.ssid, params.ssid_len); wpa_s->sme.ssid_len = params.ssid_len; params.auth_alg = WPA_AUTH_ALG_OPEN; #ifdef IEEE8021X_EAPOL if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) { if (ssid->leap) { if (ssid->non_leap == 0) params.auth_alg = WPA_AUTH_ALG_LEAP; else params.auth_alg |= WPA_AUTH_ALG_LEAP; } } #endif /* IEEE8021X_EAPOL */ wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", params.auth_alg); if (ssid->auth_alg) { params.auth_alg = ssid->auth_alg; wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: " "0x%x", params.auth_alg); } #ifdef CONFIG_SAE wpa_s->sme.sae_pmksa_caching = 0; if (wpa_key_mgmt_sae(ssid->key_mgmt)) { const u8 *rsn; struct wpa_ie_data ied; rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN); if (!rsn) { wpa_dbg(wpa_s, MSG_DEBUG, "SAE enabled, but target BSS does not advertise RSN"); } else if (wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0 && wpa_key_mgmt_sae(ied.key_mgmt)) { wpa_dbg(wpa_s, MSG_DEBUG, "Using SAE auth_alg"); params.auth_alg = WPA_AUTH_ALG_SAE; } else { wpa_dbg(wpa_s, MSG_DEBUG, "SAE enabled, but target BSS does not advertise SAE AKM for RSN"); } } #endif /* CONFIG_SAE */ for (i = 0; i < NUM_WEP_KEYS; i++) { if (ssid->wep_key_len[i]) params.wep_key[i] = ssid->wep_key[i]; params.wep_key_len[i] = ssid->wep_key_len[i]; } params.wep_tx_keyidx = ssid->wep_tx_keyidx; bssid_changed = !is_zero_ether_addr(wpa_s->bssid); os_memset(wpa_s->bssid, 0, ETH_ALEN); os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN); if (bssid_changed) wpas_notify_bssid_changed(wpa_s); if ((wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) || wpa_bss_get_ie(bss, WLAN_EID_RSN)) && wpa_key_mgmt_wpa(ssid->key_mgmt)) { int try_opportunistic; try_opportunistic = (ssid->proactive_key_caching < 0 ? wpa_s->conf->okc : ssid->proactive_key_caching) && (ssid->proto & WPA_PROTO_RSN); if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid, wpa_s->current_ssid, try_opportunistic) == 0) eapol_sm_notify_pmkid_attempt(wpa_s->eapol); wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie); if (wpa_supplicant_set_suites(wpa_s, bss, ssid, wpa_s->sme.assoc_req_ie, &wpa_s->sme.assoc_req_ie_len)) { wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA " "key management and encryption suites"); wpas_connect_work_done(wpa_s); return; } } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) { /* * Both WPA and non-WPA IEEE 802.1X enabled in configuration - * use non-WPA since the scan results did not indicate that the * AP is using WPA or WPA2. */ wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); wpa_s->sme.assoc_req_ie_len = 0; } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) { wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie); if (wpa_supplicant_set_suites(wpa_s, NULL, ssid, wpa_s->sme.assoc_req_ie, &wpa_s->sme.assoc_req_ie_len)) { wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA " "key management and encryption suites (no " "scan results)"); wpas_connect_work_done(wpa_s); return; } #ifdef CONFIG_WPS } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) { struct wpabuf *wps_ie; wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid)); if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_s->sme.assoc_req_ie)) { wpa_s->sme.assoc_req_ie_len = wpabuf_len(wps_ie); os_memcpy(wpa_s->sme.assoc_req_ie, wpabuf_head(wps_ie), wpa_s->sme.assoc_req_ie_len); } else wpa_s->sme.assoc_req_ie_len = 0; wpabuf_free(wps_ie); wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); #endif /* CONFIG_WPS */ } else { wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); wpa_s->sme.assoc_req_ie_len = 0; } #ifdef CONFIG_IEEE80211R ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN); if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN) md = ie + 2; wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0); if (md) { /* Prepare for the next transition */ wpa_ft_prepare_auth_request(wpa_s->wpa, ie); } if (md && wpa_key_mgmt_ft(ssid->key_mgmt)) { if (wpa_s->sme.assoc_req_ie_len + 5 < sizeof(wpa_s->sme.assoc_req_ie)) { struct rsn_mdie *mdie; u8 *pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len; *pos++ = WLAN_EID_MOBILITY_DOMAIN; *pos++ = sizeof(*mdie); mdie = (struct rsn_mdie *) pos; os_memcpy(mdie->mobility_domain, md, MOBILITY_DOMAIN_ID_LEN); mdie->ft_capab = md[MOBILITY_DOMAIN_ID_LEN]; wpa_s->sme.assoc_req_ie_len += 5; } if (wpa_s->sme.ft_used && os_memcmp(md, wpa_s->sme.mobility_domain, 2) == 0 && wpa_sm_has_ptk(wpa_s->wpa)) { wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying to use FT " "over-the-air"); params.auth_alg = WPA_AUTH_ALG_FT; params.ie = wpa_s->sme.ft_ies; params.ie_len = wpa_s->sme.ft_ies_len; } } #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_IEEE80211W wpa_s->sme.mfp = wpas_get_ssid_pmf(wpa_s, ssid); if (wpa_s->sme.mfp != NO_MGMT_FRAME_PROTECTION) { const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN); struct wpa_ie_data _ie; if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &_ie) == 0 && _ie.capabilities & (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) { wpa_dbg(wpa_s, MSG_DEBUG, "SME: Selected AP supports " "MFP: require MFP"); wpa_s->sme.mfp = MGMT_FRAME_PROTECTION_REQUIRED; } } #endif /* CONFIG_IEEE80211W */ #ifdef CONFIG_P2P if (wpa_s->global->p2p) { u8 *pos; size_t len; int res; pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len; len = sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len; res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len, ssid->p2p_group); if (res >= 0) wpa_s->sme.assoc_req_ie_len += res; } #endif /* CONFIG_P2P */ #ifdef CONFIG_HS20 if (is_hs20_network(wpa_s, ssid, bss)) { struct wpabuf *hs20; hs20 = wpabuf_alloc(20); if (hs20) { int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid); size_t len; wpas_hs20_add_indication(hs20, pps_mo_id); len = sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len; if (wpabuf_len(hs20) <= len) { os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len, wpabuf_head(hs20), wpabuf_len(hs20)); wpa_s->sme.assoc_req_ie_len += wpabuf_len(hs20); } wpabuf_free(hs20); } } #endif /* CONFIG_HS20 */ ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab, sizeof(ext_capab)); if (ext_capab_len > 0) { u8 *pos = wpa_s->sme.assoc_req_ie; if (wpa_s->sme.assoc_req_ie_len > 0 && pos[0] == WLAN_EID_RSN) pos += 2 + pos[1]; os_memmove(pos + ext_capab_len, pos, wpa_s->sme.assoc_req_ie_len - (pos - wpa_s->sme.assoc_req_ie)); wpa_s->sme.assoc_req_ie_len += ext_capab_len; os_memcpy(pos, ext_capab, ext_capab_len); } if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) { struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]; size_t len; len = sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len; if (wpabuf_len(buf) <= len) { os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len, wpabuf_head(buf), wpabuf_len(buf)); wpa_s->sme.assoc_req_ie_len += wpabuf_len(buf); } } sme_auth_handle_rrm(wpa_s, bss); #ifdef CONFIG_SAE if (!skip_auth && params.auth_alg == WPA_AUTH_ALG_SAE && pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid, ssid, 0) == 0) { wpa_dbg(wpa_s, MSG_DEBUG, "PMKSA cache entry found - try to use PMKSA caching instead of new SAE authentication"); params.auth_alg = WPA_AUTH_ALG_OPEN; wpa_s->sme.sae_pmksa_caching = 1; } if (!skip_auth && params.auth_alg == WPA_AUTH_ALG_SAE) { if (start) resp = sme_auth_build_sae_commit(wpa_s, ssid, bss->bssid); else resp = sme_auth_build_sae_confirm(wpa_s); if (resp == NULL) { wpas_connection_failed(wpa_s, bss->bssid, 1); return; } params.sae_data = wpabuf_head(resp); params.sae_data_len = wpabuf_len(resp); wpa_s->sme.sae.state = start ? SAE_COMMITTED : SAE_CONFIRMED; } #endif /* CONFIG_SAE */ wpa_supplicant_cancel_sched_scan(wpa_s); wpa_supplicant_cancel_scan(wpa_s); wpa_msg(wpa_s, MSG_INFO, "SME: Trying to authenticate with " MACSTR " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid), wpa_ssid_txt(params.ssid, params.ssid_len), params.freq); wpa_clear_keys(wpa_s, bss->bssid); wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING); old_ssid = wpa_s->current_ssid; wpa_s->current_ssid = ssid; wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid); wpa_supplicant_initiate_eapol(wpa_s); if (old_ssid != wpa_s->current_ssid) wpas_notify_network_changed(wpa_s); #ifdef CONFIG_P2P /* * If multi-channel concurrency is not supported, check for any * frequency conflict. In case of any frequency conflict, remove the * least prioritized connection. */ if (wpa_s->num_multichan_concurrent < 2) { int freq, num; num = get_shared_radio_freqs(wpa_s, &freq, 1); if (num > 0 && freq > 0 && freq != params.freq) { wpa_printf(MSG_DEBUG, "Conflicting frequency found (%d != %d)", freq, params.freq); if (wpas_p2p_handle_frequency_conflicts(wpa_s, params.freq, ssid) < 0) { wpas_connection_failed(wpa_s, bss->bssid, 0); wpa_supplicant_mark_disassoc(wpa_s); wpabuf_free(resp); wpas_connect_work_done(wpa_s); return; } } } #endif /* CONFIG_P2P */ if (skip_auth) { wpa_msg(wpa_s, MSG_DEBUG, "SME: Skip authentication step on reassoc-to-same-BSS"); wpabuf_free(resp); sme_associate(wpa_s, ssid->mode, bss->bssid, WLAN_AUTH_OPEN); return; } wpa_s->sme.auth_alg = params.auth_alg; if (wpa_drv_authenticate(wpa_s, ¶ms) < 0) { wpa_msg(wpa_s, MSG_INFO, "SME: Authentication request to the " "driver failed"); wpas_connection_failed(wpa_s, bss->bssid, 1); wpa_supplicant_mark_disassoc(wpa_s); wpabuf_free(resp); wpas_connect_work_done(wpa_s); return; } eloop_register_timeout(SME_AUTH_TIMEOUT, 0, sme_auth_timer, wpa_s, NULL); /* * Association will be started based on the authentication event from * the driver. */ wpabuf_free(resp); }
os_err_t Q_Sh_rx_callback(char data) { char Recieve=data; // osmemset(&shell,0,sizeof(struct finsh_shell)); if (Recieve == 0x1b) { shell.status = WAIT_SPEC_KEY; goto end; } else if (shell.status == WAIT_SPEC_KEY) { if (Recieve == 0x5b) { shell.status = WAIT_FUNC_KEY; goto end; } shell.status = WAIT_NORMAL; } else if (shell.status == WAIT_FUNC_KEY) { shell.status = WAIT_NORMAL; if (Recieve == 0x44) /* left key */ { if (shell.line_curpos) { printf("\b"); shell.line_curpos --; } goto end; } else if (Recieve == 0x43) /* right key */ { if (shell.line_curpos < shell.line_position) { printf("%c", shell.line[shell.line_curpos]); shell.line_curpos ++; } goto end; } } if(Recieve==13)//»Ø³µ { shell.line[shell.line_position]=0; printf("\n\r"); if(shell.line_position>0||!(shell.ifpass)) { Q_Sh_CmdHandler(0,shell.line); } shell.line_position=0; shell.line_curpos=0; printf("\n\rWSHOS>>"); } /* handle backspace key */ else if(Recieve == 0x7f || Recieve == 0x08)//»Øɾ { if(shell.line_curpos>0) { shell.line_position--; shell.line_curpos--; if (shell.line_position > shell.line_curpos) { u16 i; os_memmove(&shell.line[shell.line_curpos], &shell.line[shell.line_curpos + 1], shell.line_position - shell.line_curpos); shell.line[shell.line_position] = 0; printf("\b%s \b", &shell.line[shell.line_curpos]); /* move the cursor to the origin position */ for (i = shell.line_curpos; i <= shell.line_position; i++) printf("\b"); }else { shell.line[(shell.line_position)]=0; printf("\b \b"); } } } if(shell.line_position>=SHELL_CMD_SIZE) { shell.line_position=0;//³¬³ö·¶Î§£¬¾ÍÍ£Ö¹¼ÓÈëеÄÁË¡£ shell.line_curpos=0;//³¬³ö·¶Î§£¬¾ÍÍ£Ö¹¼ÓÈëеÄÁË¡ } if(Recieve>=0x20) { if (shell.line_position > shell.line_curpos) { u16 i; os_memmove(&shell.line[shell.line_curpos + 1], &shell.line[shell.line_curpos], shell.line_position - shell.line_curpos); shell.line[shell.line_curpos] = Recieve; shell.line[shell.line_position+1] = 0; printf("%s", &shell.line[shell.line_curpos]); /* move the cursor to the origin position */ for (i = shell.line_curpos; i < shell.line_position; i++) printf("\b"); }else { shell.line[(shell.line_position)]=Recieve; shell.line[shell.line_curpos+1] = 0; printf("%c",Recieve); } shell.line_position++; shell.line_curpos++; } end: return SUCCESS; }
unsigned short btchip_apdu_get_trusted_input() { unsigned char apduLength; unsigned char dataOffset = 0; unsigned char trustedInputSignature[32]; cx_sha256_t hash; apduLength = G_io_apdu_buffer[ISO_OFFSET_LC]; SB_CHECK(N_btchip.bkp.config.operationMode); switch (SB_GET(N_btchip.bkp.config.operationMode)) { case BTCHIP_MODE_WALLET: case BTCHIP_MODE_RELAXED_WALLET: case BTCHIP_MODE_SERVER: break; default: return BTCHIP_SW_CONDITIONS_OF_USE_NOT_SATISFIED; } if (G_io_apdu_buffer[ISO_OFFSET_P1] == GET_TRUSTED_INPUT_P1_FIRST) { // Initialize btchip_context_D.transactionTargetInput = btchip_read_u32(G_io_apdu_buffer + ISO_OFFSET_CDATA, 1, 0); btchip_context_D.transactionContext.transactionState = BTCHIP_TRANSACTION_NONE; btchip_context_D.trustedInputProcessed = 0; btchip_context_D.transactionContext.consumeP2SH = 0; btchip_set_check_internal_structure_integrity(1); dataOffset = 4; btchip_context_D.transactionHashOption = TRANSACTION_HASH_FULL; btchip_context_D.usingSegwit = 0; } else if (G_io_apdu_buffer[ISO_OFFSET_P1] != GET_TRUSTED_INPUT_P1_NEXT) { return BTCHIP_SW_INCORRECT_P1_P2; } if (G_io_apdu_buffer[ISO_OFFSET_P2] != 0x00) { return BTCHIP_SW_INCORRECT_P1_P2; } btchip_context_D.transactionBufferPointer = G_io_apdu_buffer + ISO_OFFSET_CDATA + dataOffset; btchip_context_D.transactionDataRemaining = apduLength - dataOffset; transaction_parse(PARSE_MODE_TRUSTED_INPUT); if (btchip_context_D.transactionContext.transactionState == BTCHIP_TRANSACTION_PARSED) { unsigned char targetHash[32]; btchip_context_D.transactionContext.transactionState = BTCHIP_TRANSACTION_NONE; btchip_set_check_internal_structure_integrity(1); if (!btchip_context_D.trustedInputProcessed) { // Output was not found return BTCHIP_SW_INCORRECT_DATA; } cx_hash(&btchip_context_D.transactionHashFull.sha256.header, CX_LAST, (unsigned char *)NULL, 0, targetHash, 32); // Otherwise prepare cx_rng(G_io_apdu_buffer, 8); G_io_apdu_buffer[0] = MAGIC_TRUSTED_INPUT; G_io_apdu_buffer[1] = 0x00; cx_sha256_init(&hash); cx_hash(&hash.header, CX_LAST, targetHash, 32, G_io_apdu_buffer + 4, 32); btchip_write_u32_le(G_io_apdu_buffer + 4 + 32, btchip_context_D.transactionTargetInput); os_memmove(G_io_apdu_buffer + 4 + 32 + 4, btchip_context_D.transactionContext.transactionAmount, 8); cx_hmac_sha256(N_btchip.bkp.trustedinput_key, sizeof(N_btchip.bkp.trustedinput_key), G_io_apdu_buffer, TRUSTEDINPUT_SIZE, trustedInputSignature, 32); os_memmove(G_io_apdu_buffer + TRUSTEDINPUT_SIZE, trustedInputSignature, 8); btchip_context_D.outLength = 0x38; } return BTCHIP_SW_OK; }
void transaction_parse(unsigned char parseMode) { unsigned char optionP2SHSkip2FA = ((N_btchip.bkp.config.options & BTCHIP_OPTION_SKIP_2FA_P2SH) != 0); btchip_set_check_internal_structure_integrity(0); BEGIN_TRY { TRY { for (;;) { switch (btchip_context_D.transactionContext.transactionState) { case BTCHIP_TRANSACTION_NONE: { PRINTF("Init transaction parser\n"); // Reset transaction state btchip_context_D.transactionContext .transactionRemainingInputsOutputs = 0; btchip_context_D.transactionContext .transactionCurrentInputOutput = 0; btchip_context_D.transactionContext.scriptRemaining = 0; os_memset( btchip_context_D.transactionContext.transactionAmount, 0, sizeof(btchip_context_D.transactionContext .transactionAmount)); // TODO : transactionControlFid // Reset hashes if (btchip_context_D.usingOverwinter) { if (btchip_context_D.segwitParsedOnce) { uint8_t parameters[16]; os_memmove(parameters, OVERWINTER_PARAM_SIGHASH, 16); btchip_write_u32_le(parameters + 12, btchip_context_D.usingOverwinter == ZCASH_USING_OVERWINTER_SAPLING ? CONSENSUS_BRANCH_ID_SAPLING : CONSENSUS_BRANCH_ID_OVERWINTER); cx_blake2b_init2(&btchip_context_D.transactionHashFull.blake2b, 256, NULL, 0, parameters, 16); } } else { cx_sha256_init(&btchip_context_D.transactionHashFull.sha256); } cx_sha256_init( &btchip_context_D.transactionHashAuthorization); if (btchip_context_D.usingSegwit) { btchip_context_D.transactionHashOption = 0; if (!btchip_context_D.segwitParsedOnce) { if (btchip_context_D.usingOverwinter) { cx_blake2b_init2(&btchip_context_D.segwit.hash.hashPrevouts.blake2b, 256, NULL, 0, OVERWINTER_PARAM_PREVOUTS, 16); cx_blake2b_init2(&btchip_context_D.transactionHashFull.blake2b, 256, NULL, 0, OVERWINTER_PARAM_SEQUENCE, 16); } else { cx_sha256_init( &btchip_context_D.segwit.hash.hashPrevouts.sha256); } } else { PRINTF("Resume SegWit hash\n"); PRINTF("SEGWIT Version\n%.*H\n",sizeof(btchip_context_D.transactionVersion),btchip_context_D.transactionVersion); PRINTF("SEGWIT HashedPrevouts\n%.*H\n",sizeof(btchip_context_D.segwit.cache.hashedPrevouts),btchip_context_D.segwit.cache.hashedPrevouts); PRINTF("SEGWIT HashedSequence\n%.*H\n",sizeof(btchip_context_D.segwit.cache.hashedSequence),btchip_context_D.segwit.cache.hashedSequence); if (btchip_context_D.usingOverwinter) { cx_hash(&btchip_context_D.transactionHashFull.blake2b.header, 0, btchip_context_D.transactionVersion, sizeof(btchip_context_D.transactionVersion), NULL, 0); cx_hash(&btchip_context_D.transactionHashFull.blake2b.header, 0, btchip_context_D.nVersionGroupId, sizeof(btchip_context_D.nVersionGroupId), NULL, 0); cx_hash(&btchip_context_D.transactionHashFull.blake2b.header, 0, btchip_context_D.segwit.cache.hashedPrevouts, sizeof(btchip_context_D.segwit.cache.hashedPrevouts), NULL, 0); cx_hash(&btchip_context_D.transactionHashFull.blake2b.header, 0, btchip_context_D.segwit.cache.hashedSequence, sizeof(btchip_context_D.segwit.cache.hashedSequence), NULL, 0); cx_hash(&btchip_context_D.transactionHashFull.blake2b.header, 0, btchip_context_D.segwit.cache.hashedOutputs, sizeof(btchip_context_D.segwit.cache.hashedOutputs), NULL, 0); cx_hash(&btchip_context_D.transactionHashFull.blake2b.header, 0, OVERWINTER_NO_JOINSPLITS, 32, NULL, 0); if (btchip_context_D.usingOverwinter == ZCASH_USING_OVERWINTER_SAPLING) { cx_hash(&btchip_context_D.transactionHashFull.blake2b.header, 0, OVERWINTER_NO_JOINSPLITS, 32, NULL, 0); // sapling hashShieldedSpends cx_hash(&btchip_context_D.transactionHashFull.blake2b.header, 0, OVERWINTER_NO_JOINSPLITS, 32, NULL, 0); // sapling hashShieldedOutputs } cx_hash(&btchip_context_D.transactionHashFull.blake2b.header, 0, btchip_context_D.nLockTime, sizeof(btchip_context_D.nLockTime), NULL, 0); cx_hash(&btchip_context_D.transactionHashFull.blake2b.header, 0, btchip_context_D.nExpiryHeight, sizeof(btchip_context_D.nExpiryHeight), NULL, 0); if (btchip_context_D.usingOverwinter == ZCASH_USING_OVERWINTER_SAPLING) { unsigned char valueBalance[8]; os_memset(valueBalance, 0, sizeof(valueBalance)); cx_hash(&btchip_context_D.transactionHashFull.blake2b.header, 0, valueBalance, sizeof(valueBalance), NULL, 0); // sapling valueBalance } cx_hash(&btchip_context_D.transactionHashFull.blake2b.header, 0, btchip_context_D.sigHashType, sizeof(btchip_context_D.sigHashType), NULL, 0); } else { cx_hash( &btchip_context_D.transactionHashFull.sha256.header, 0, btchip_context_D.transactionVersion, sizeof(btchip_context_D.transactionVersion), NULL, 0); cx_hash( &btchip_context_D.transactionHashFull.sha256.header, 0, btchip_context_D.segwit.cache.hashedPrevouts, sizeof(btchip_context_D.segwit.cache .hashedPrevouts), NULL, 0); cx_hash( &btchip_context_D.transactionHashFull.sha256.header, 0, btchip_context_D.segwit.cache.hashedSequence, sizeof(btchip_context_D.segwit.cache .hashedSequence), NULL, 0); cx_hash(&btchip_context_D .transactionHashAuthorization.header, 0, (unsigned char *)&btchip_context_D .segwit.cache, sizeof(btchip_context_D.segwit.cache), NULL, 0); } } } // Parse the beginning of the transaction // Version check_transaction_available(4); os_memmove(btchip_context_D.transactionVersion, btchip_context_D.transactionBufferPointer, 4); transaction_offset_increase(4); if (btchip_context_D.usingOverwinter) { // nVersionGroupId check_transaction_available(4); os_memmove(btchip_context_D.nVersionGroupId, btchip_context_D.transactionBufferPointer, 4); transaction_offset_increase(4); } if (G_coin_config->flags & FLAG_PEERCOIN_SUPPORT) { if (btchip_context_D.coinFamily == BTCHIP_FAMILY_PEERCOIN) { // Timestamp check_transaction_available(4); transaction_offset_increase(4); } } // Number of inputs btchip_context_D.transactionContext .transactionRemainingInputsOutputs = transaction_get_varint(); PRINTF("Number of inputs : " DEBUG_LONG "\n",btchip_context_D.transactionContext.transactionRemainingInputsOutputs); // Ready to proceed btchip_context_D.transactionContext.transactionState = BTCHIP_TRANSACTION_DEFINED_WAIT_INPUT; // no break is intentional } case BTCHIP_TRANSACTION_DEFINED_WAIT_INPUT: { unsigned char trustedInputFlag = 1; PRINTF("Process input\n"); if (btchip_context_D.transactionContext .transactionRemainingInputsOutputs == 0) { // No more inputs to hash, move forward btchip_context_D.transactionContext.transactionState = BTCHIP_TRANSACTION_INPUT_HASHING_DONE; continue; } if (btchip_context_D.transactionDataRemaining < 1) { // No more data to read, ok goto ok; } // Proceed with the next input if (parseMode == PARSE_MODE_TRUSTED_INPUT) { check_transaction_available( 36); // prevout : 32 hash + 4 index transaction_offset_increase(36); } if (parseMode == PARSE_MODE_SIGNATURE) { unsigned char trustedInputLength; unsigned char trustedInput[0x38]; unsigned char amount[8]; unsigned char *savePointer; // Expect the trusted input flag and trusted input // length check_transaction_available(2); switch (*btchip_context_D.transactionBufferPointer) { case 0: if (btchip_context_D.usingSegwit) { PRINTF("Non trusted input used in segwit mode"); goto fail; } trustedInputFlag = 0; break; case 1: if (btchip_context_D.usingSegwit) { PRINTF("Trusted input used in segwit mode"); goto fail; } trustedInputFlag = 1; break; case 2: if (!btchip_context_D.usingSegwit) { PRINTF("Segwit input not used in segwit mode"); goto fail; } break; default: PRINTF("Invalid trusted input flag\n"); goto fail; } /* trustedInputLength = *(btchip_context_D.transactionBufferPointer + 1); if (trustedInputLength > sizeof(trustedInput)) { PRINTF("Trusted input too long\n"); goto fail; } */ if (btchip_context_D.usingSegwit) { transaction_offset_increase(1); check_transaction_available( 36); // prevout : 32 hash + 4 index if (!btchip_context_D.segwitParsedOnce) { if (btchip_context_D.usingOverwinter) { cx_hash(&btchip_context_D.segwit.hash.hashPrevouts.blake2b.header, 0, btchip_context_D.transactionBufferPointer, 36, NULL, 0); } else { cx_hash( &btchip_context_D.segwit.hash.hashPrevouts .sha256.header, 0, btchip_context_D.transactionBufferPointer, 36, NULL, 0); } transaction_offset_increase(36); check_transaction_available(8); // update amount btchip_swap_bytes( amount, btchip_context_D.transactionBufferPointer, 8); if (transaction_amount_add_be( btchip_context_D.transactionContext .transactionAmount, btchip_context_D.transactionContext .transactionAmount, amount)) { PRINTF("Overflow\n"); goto fail; } PRINTF("Adding amount\n%.*H\n",8,btchip_context_D.transactionBufferPointer); PRINTF("New amount\n%.*H\n",8,btchip_context_D.transactionContext.transactionAmount); transaction_offset_increase(8); } else { btchip_context_D.transactionHashOption = TRANSACTION_HASH_FULL; transaction_offset_increase(36); btchip_context_D.transactionHashOption = 0; check_transaction_available(8); // save amount os_memmove( btchip_context_D.inputValue, btchip_context_D.transactionBufferPointer, 8); transaction_offset_increase(8); btchip_context_D.transactionHashOption = TRANSACTION_HASH_FULL; } } else if (!trustedInputFlag) { // Only authorized in relaxed wallet and server // modes SB_CHECK(N_btchip.bkp.config.operationMode); switch (SB_GET(N_btchip.bkp.config.operationMode)) { case BTCHIP_MODE_WALLET: if (!optionP2SHSkip2FA) { PRINTF("Untrusted input not authorized\n"); goto fail; } break; case BTCHIP_MODE_RELAXED_WALLET: case BTCHIP_MODE_SERVER: break; default: PRINTF("Untrusted input not authorized\n"); goto fail; } btchip_context_D.transactionBufferPointer++; btchip_context_D.transactionDataRemaining--; check_transaction_available( 36); // prevout : 32 hash + 4 index transaction_offset_increase(36); PRINTF("Marking relaxed input\n"); btchip_context_D.transactionContext.relaxed = 1; /* PRINTF("Clearing P2SH consumption\n"); btchip_context_D.transactionContext.consumeP2SH = 0; */ } else { trustedInputLength = *( btchip_context_D.transactionBufferPointer + 1); if ((trustedInputLength > sizeof(trustedInput)) || (trustedInputLength < 8)) { PRINTF("Invalid trusted input size\n"); goto fail; } check_transaction_available(2 + trustedInputLength); cx_hmac_sha256( N_btchip.bkp.trustedinput_key, sizeof(N_btchip.bkp.trustedinput_key), btchip_context_D.transactionBufferPointer + 2, trustedInputLength - 8, trustedInput, trustedInputLength); if (btchip_secure_memcmp( trustedInput, btchip_context_D.transactionBufferPointer + 2 + trustedInputLength - 8, 8) != 0) { PRINTF("Invalid signature\n"); goto fail; } os_memmove( trustedInput, btchip_context_D.transactionBufferPointer + 2, trustedInputLength - 8); if (trustedInput[0] != MAGIC_TRUSTED_INPUT) { PRINTF("Failed to verify trusted input signature\n"); goto fail; } // Update the hash with prevout data savePointer = btchip_context_D.transactionBufferPointer; /* // Check if a P2SH script is used if ((trustedInput[1] & FLAG_TRUSTED_INPUT_P2SH) == 0) { PRINTF("Clearing P2SH consumption\n"); btchip_context_D.transactionContext.consumeP2SH = 0; } */ btchip_context_D.transactionBufferPointer = trustedInput + 4; PRINTF("Trusted input hash\n%.*H\n",36,btchip_context_D.transactionBufferPointer); transaction_offset(36); btchip_context_D.transactionBufferPointer = savePointer + (2 + trustedInputLength); btchip_context_D.transactionDataRemaining -= (2 + trustedInputLength); // Update the amount btchip_swap_bytes(amount, trustedInput + 40, 8); if (transaction_amount_add_be( btchip_context_D.transactionContext .transactionAmount, btchip_context_D.transactionContext .transactionAmount, amount)) { PRINTF("Overflow\n"); goto fail; } PRINTF("Adding amount\n%.*H\n",8,(trustedInput + 40)); PRINTF("New amount\n%.*H\n",8,btchip_context_D.transactionContext.transactionAmount); } if (!btchip_context_D.usingSegwit) { // Do not include the input script length + value in // the authentication hash btchip_context_D.transactionHashOption = TRANSACTION_HASH_FULL; } } // Read the script length btchip_context_D.transactionContext.scriptRemaining = transaction_get_varint(); PRINTF("Script to read " DEBUG_LONG "\n",btchip_context_D.transactionContext.scriptRemaining); if ((parseMode == PARSE_MODE_SIGNATURE) && !trustedInputFlag && !btchip_context_D.usingSegwit) { // Only proceeds if this is not to be signed - so length // should be null if (btchip_context_D.transactionContext .scriptRemaining != 0) { PRINTF("Request to sign relaxed input\n"); if (!optionP2SHSkip2FA) { goto fail; } } } // Move on btchip_context_D.transactionContext.transactionState = BTCHIP_TRANSACTION_INPUT_HASHING_IN_PROGRESS_INPUT_SCRIPT; // no break is intentional } case BTCHIP_TRANSACTION_INPUT_HASHING_IN_PROGRESS_INPUT_SCRIPT: { unsigned char dataAvailable; PRINTF("Process input script, remaining " DEBUG_LONG "\n",btchip_context_D.transactionContext.scriptRemaining); if (btchip_context_D.transactionDataRemaining < 1) { // No more data to read, ok goto ok; } // Scan for P2SH consumption - huge shortcut, but fine // enough // Also usable in SegWit mode if (btchip_context_D.transactionContext.scriptRemaining == 1) { if (*btchip_context_D.transactionBufferPointer == OP_CHECKMULTISIG) { if (optionP2SHSkip2FA) { PRINTF("Marking P2SH consumption\n"); btchip_context_D.transactionContext .consumeP2SH = 1; } } else { // When using the P2SH shortcut, all inputs must use // P2SH PRINTF("Disabling P2SH consumption\n"); btchip_context_D.transactionContext.consumeP2SH = 0; } transaction_offset_increase(1); btchip_context_D.transactionContext.scriptRemaining--; } if (btchip_context_D.transactionContext.scriptRemaining == 0) { if (parseMode == PARSE_MODE_SIGNATURE) { if (!btchip_context_D.usingSegwit) { // Restore dual hash for signature + // authentication btchip_context_D.transactionHashOption = TRANSACTION_HASH_BOTH; } else { if (btchip_context_D.segwitParsedOnce) { // Append the saved value PRINTF("SEGWIT Add value\n%.*H\n",8,btchip_context_D.inputValue); if (btchip_context_D.usingOverwinter) { cx_hash(&btchip_context_D.transactionHashFull.blake2b.header, 0, btchip_context_D.inputValue, 8, NULL, 0); } else { cx_hash(&btchip_context_D .transactionHashFull.sha256.header, 0, btchip_context_D.inputValue, 8, NULL, 0); } } } } // Sequence check_transaction_available(4); if (btchip_context_D.usingSegwit && !btchip_context_D.segwitParsedOnce) { if (btchip_context_D.usingOverwinter) { cx_hash(&btchip_context_D.transactionHashFull.blake2b.header, 0, btchip_context_D.transactionBufferPointer, 4, NULL, 0); } else { cx_hash(&btchip_context_D.transactionHashFull .sha256.header, 0, btchip_context_D.transactionBufferPointer, 4, NULL, 0); } } transaction_offset_increase(4); // Move to next input btchip_context_D.transactionContext .transactionRemainingInputsOutputs--; btchip_context_D.transactionContext .transactionCurrentInputOutput++; btchip_context_D.transactionContext.transactionState = BTCHIP_TRANSACTION_DEFINED_WAIT_INPUT; continue; } // Save the last script byte for the P2SH check dataAvailable = (btchip_context_D.transactionDataRemaining > btchip_context_D.transactionContext .scriptRemaining - 1 ? btchip_context_D.transactionContext .scriptRemaining - 1 : btchip_context_D.transactionDataRemaining); if (dataAvailable == 0) { goto ok; } transaction_offset_increase(dataAvailable); btchip_context_D.transactionContext.scriptRemaining -= dataAvailable; break; } case BTCHIP_TRANSACTION_INPUT_HASHING_DONE: { PRINTF("Input hashing done\n"); if (parseMode == PARSE_MODE_SIGNATURE) { // inputs have been prepared, stop the parsing here if (btchip_context_D.usingSegwit && !btchip_context_D.segwitParsedOnce) { unsigned char hashedPrevouts[32]; unsigned char hashedSequence[32]; // Flush the cache if (btchip_context_D.usingOverwinter) { cx_hash(&btchip_context_D.segwit.hash.hashPrevouts.blake2b.header, CX_LAST, hashedPrevouts, 0, hashedPrevouts, 32); cx_hash(&btchip_context_D.transactionHashFull.blake2b.header, CX_LAST, hashedSequence, 0, hashedSequence, 32); } else { cx_hash(&btchip_context_D.segwit.hash.hashPrevouts .sha256.header, CX_LAST, hashedPrevouts, 0, hashedPrevouts, 32); cx_sha256_init( &btchip_context_D.segwit.hash.hashPrevouts.sha256); cx_hash(&btchip_context_D.segwit.hash.hashPrevouts .sha256.header, CX_LAST, hashedPrevouts, sizeof(hashedPrevouts), hashedPrevouts, 32); cx_hash(&btchip_context_D.transactionHashFull .sha256.header, CX_LAST, hashedSequence, 0, hashedSequence, 32); cx_sha256_init( &btchip_context_D.transactionHashFull.sha256); cx_hash(&btchip_context_D.transactionHashFull .sha256.header, CX_LAST, hashedSequence, sizeof(hashedSequence), hashedSequence, 32); } os_memmove( btchip_context_D.segwit.cache.hashedPrevouts, hashedPrevouts, sizeof(hashedPrevouts)); os_memmove( btchip_context_D.segwit.cache.hashedSequence, hashedSequence, sizeof(hashedSequence)); PRINTF("hashPrevout\n%.*H\n",32,btchip_context_D.segwit.cache.hashedPrevouts); PRINTF("hashSequence\n%.*H\n",32,btchip_context_D.segwit.cache.hashedSequence); } if (btchip_context_D.usingSegwit && btchip_context_D.segwitParsedOnce) { if (!btchip_context_D.usingOverwinter) { PRINTF("SEGWIT hashedOutputs\n%.*H\n",sizeof(btchip_context_D.segwit.cache.hashedOutputs),btchip_context_D.segwit.cache.hashedOutputs); cx_hash( &btchip_context_D.transactionHashFull.sha256.header, 0, btchip_context_D.segwit.cache.hashedOutputs, sizeof(btchip_context_D.segwit.cache .hashedOutputs), NULL, 0); } btchip_context_D.transactionContext .transactionState = BTCHIP_TRANSACTION_SIGN_READY; } else { btchip_context_D.transactionContext .transactionState = BTCHIP_TRANSACTION_PRESIGN_READY; if (btchip_context_D.usingOverwinter) { cx_blake2b_init2(&btchip_context_D.transactionHashFull.blake2b, 256, NULL, 0, OVERWINTER_PARAM_OUTPUTS, 16); } else if (btchip_context_D.usingSegwit) { cx_sha256_init(&btchip_context_D.transactionHashFull.sha256); } } continue; } if (btchip_context_D.transactionDataRemaining < 1) { // No more data to read, ok goto ok; } // Number of outputs btchip_context_D.transactionContext .transactionRemainingInputsOutputs = transaction_get_varint(); btchip_context_D.transactionContext .transactionCurrentInputOutput = 0; PRINTF("Number of outputs : " DEBUG_LONG "\n", btchip_context_D.transactionContext .transactionRemainingInputsOutputs); // Ready to proceed btchip_context_D.transactionContext.transactionState = BTCHIP_TRANSACTION_DEFINED_WAIT_OUTPUT; // no break is intentional } case BTCHIP_TRANSACTION_DEFINED_WAIT_OUTPUT: { if (btchip_context_D.transactionContext .transactionRemainingInputsOutputs == 0) { // No more outputs to hash, move forward btchip_context_D.transactionContext.transactionState = BTCHIP_TRANSACTION_OUTPUT_HASHING_DONE; continue; } if (btchip_context_D.transactionDataRemaining < 1) { // No more data to read, ok goto ok; } // Amount check_transaction_available(8); if ((parseMode == PARSE_MODE_TRUSTED_INPUT) && (btchip_context_D.transactionContext .transactionCurrentInputOutput == btchip_context_D.transactionTargetInput)) { // Save the amount os_memmove(btchip_context_D.transactionContext .transactionAmount, btchip_context_D.transactionBufferPointer, 8); btchip_context_D.trustedInputProcessed = 1; } transaction_offset_increase(8); // Read the script length btchip_context_D.transactionContext.scriptRemaining = transaction_get_varint(); PRINTF("Script to read " DEBUG_LONG "\n",btchip_context_D.transactionContext.scriptRemaining); // Move on btchip_context_D.transactionContext.transactionState = BTCHIP_TRANSACTION_OUTPUT_HASHING_IN_PROGRESS_OUTPUT_SCRIPT; // no break is intentional } case BTCHIP_TRANSACTION_OUTPUT_HASHING_IN_PROGRESS_OUTPUT_SCRIPT: { unsigned char dataAvailable; PRINTF("Process output script, remaining " DEBUG_LONG "\n",btchip_context_D.transactionContext.scriptRemaining); /* // Special check if consuming a P2SH script if (parseMode == PARSE_MODE_TRUSTED_INPUT) { // Assume the full input script is sent in a single APDU, then do the ghetto validation if ((btchip_context_D.transactionBufferPointer[0] == OP_HASH160) && (btchip_context_D.transactionBufferPointer[btchip_context_D.transactionDataRemaining - 1] == OP_EQUAL)) { PRINTF("Marking P2SH output\n"); btchip_context_D.transactionContext.consumeP2SH = 1; } } */ if (btchip_context_D.transactionDataRemaining < 1) { // No more data to read, ok goto ok; } if (btchip_context_D.transactionContext.scriptRemaining == 0) { // Move to next output btchip_context_D.transactionContext .transactionRemainingInputsOutputs--; btchip_context_D.transactionContext .transactionCurrentInputOutput++; btchip_context_D.transactionContext.transactionState = BTCHIP_TRANSACTION_DEFINED_WAIT_OUTPUT; continue; } dataAvailable = (btchip_context_D.transactionDataRemaining > btchip_context_D.transactionContext .scriptRemaining ? btchip_context_D.transactionContext .scriptRemaining : btchip_context_D.transactionDataRemaining); if (dataAvailable == 0) { goto ok; } transaction_offset_increase(dataAvailable); btchip_context_D.transactionContext.scriptRemaining -= dataAvailable; break; } case BTCHIP_TRANSACTION_OUTPUT_HASHING_DONE: { PRINTF("Output hashing done\n"); if (btchip_context_D.transactionDataRemaining < 1) { // No more data to read, ok goto ok; } // Locktime check_transaction_available(4); transaction_offset_increase(4); if (btchip_context_D.transactionDataRemaining == 0) { btchip_context_D.transactionContext.transactionState = BTCHIP_TRANSACTION_PARSED; continue; } else { btchip_context_D.transactionHashOption = 0; btchip_context_D.transactionContext.scriptRemaining = transaction_get_varint(); btchip_context_D.transactionHashOption = TRANSACTION_HASH_FULL; btchip_context_D.transactionContext.transactionState = BTCHIP_TRANSACTION_PROCESS_EXTRA; continue; } } case BTCHIP_TRANSACTION_PROCESS_EXTRA: { unsigned char dataAvailable; if (btchip_context_D.transactionContext.scriptRemaining == 0) { btchip_context_D.transactionContext.transactionState = BTCHIP_TRANSACTION_PARSED; continue; } if (btchip_context_D.transactionDataRemaining < 1) { // No more data to read, ok goto ok; } dataAvailable = (btchip_context_D.transactionDataRemaining > btchip_context_D.transactionContext .scriptRemaining ? btchip_context_D.transactionContext .scriptRemaining : btchip_context_D.transactionDataRemaining); if (dataAvailable == 0) { goto ok; } transaction_offset_increase(dataAvailable); btchip_context_D.transactionContext.scriptRemaining -= dataAvailable; break; } case BTCHIP_TRANSACTION_PARSED: { PRINTF("Transaction parsed\n"); goto ok; } case BTCHIP_TRANSACTION_PRESIGN_READY: { PRINTF("Presign ready\n"); goto ok; } case BTCHIP_TRANSACTION_SIGN_READY: { PRINTF("Sign ready\n"); goto ok; } } } fail: PRINTF("Transaction parse - fail\n"); THROW(EXCEPTION); ok : {} } CATCH_OTHER(e) { PRINTF("Transaction parse - surprise fail\n"); btchip_context_D.transactionContext.transactionState = BTCHIP_TRANSACTION_NONE; btchip_set_check_internal_structure_integrity(1); THROW(e); } // before the finally to restore the surrounding context if an exception // is raised during finally FINALLY { btchip_set_check_internal_structure_integrity(1); } } END_TRY; }