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++;
	}
}
Example #2
0
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;
}
Example #3
0
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;
}
Example #4
0
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);
}
Example #5
0
/**
 * 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;
}
Example #6
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;
}
Example #8
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 
              );
}
Example #9
0
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 */
}
Example #10
0
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);
}
Example #11
0
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;
}
Example #12
0
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

}
Example #13
0
//*****************************************************************************
// 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--;
	}
}
Example #14
0
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;
}
Example #15
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;
}
Example #17
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;
}
Example #18
0
/*
 * 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);
    }
Example #19
0
/**
 * 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;
}
Example #20
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;
    }
}
Example #21
0
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--;
}
Example #22
0
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(&params, 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, &params) < 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.
	 */
}
Example #24
0
File: sme.c Project: denehs/hostap
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(&params, 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, &params) < 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.
	 */
}
Example #25
0
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(&params, 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, &params) < 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);
}
Example #28
0
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;
}