Example #1
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 #2
0
/**
 * encrypt_pw_block_with_password_hash - EncryptPwBlockWithPasswordHash() - RFC 2759, Sect. 8.10
 * @password: 0-to-256-unicode-char Password (IN; ASCII)
 * @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 i, offset;
    u8 *pos;

    if (password_len > 256)
        return -1;

    os_memset(pw_block, 0, PWBLOCK_LEN);
    offset = (256 - password_len) * 2;
    if (os_get_random(pw_block, offset) < 0)
        return -1;
    for (i = 0; i < password_len; i++)
        pw_block[offset + i * 2] = password[i];
    /*
     * 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 #3
0
/* Decrypt RSN EAPOL-Key key data (RC4 or AES-WRAP) */
static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm,
					   struct wpa_eapol_key *key, u16 ver)
{
	u16 keydatalen = WPA_GET_BE16(key->key_data_length);

	wpa_hexdump(MSG_DEBUG, "RSN: encrypted key data",
		    (u8 *) (key + 1), keydatalen);
	if (!sm->ptk_set) {
		wpa_printf(MSG_WARNING, "WPA: PTK not available, "
			   "cannot decrypt EAPOL-Key key data.");
		return -1;
	}

	/* Decrypt key data here so that this operation does not need
	 * to be implemented separately for each message type. */
	if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4) {
		u8 ek[32];
		os_memcpy(ek, key->key_iv, 16);
		os_memcpy(ek + 16, sm->ptk.kek, 16);
		if (rc4_skip(ek, 32, 256, (u8 *) (key + 1), keydatalen)) {
			wpa_printf(MSG_ERROR, "WPA: RC4 failed");
			return -1;
		}
	} else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
		   ver == WPA_KEY_INFO_TYPE_AES_128_CMAC) {
		u8 *buf;
		if (keydatalen % 8) {
			wpa_printf(MSG_WARNING, "WPA: Unsupported "
				   "AES-WRAP len %d", keydatalen);
			return -1;
		}
		keydatalen -= 8; /* AES-WRAP adds 8 bytes */
		buf = os_malloc(keydatalen);
		if (buf == NULL) {
			wpa_printf(MSG_WARNING, "WPA: No memory for "
				   "AES-UNWRAP buffer");
			return -1;
		}
		if (aes_unwrap(sm->ptk.kek, keydatalen / 8,
			       (u8 *) (key + 1), buf)) {
			os_free(buf);
			wpa_printf(MSG_WARNING, "WPA: AES unwrap failed - "
				   "could not decrypt EAPOL-Key key data");
			return -1;
		}
		os_memcpy(key + 1, buf, keydatalen);
		os_free(buf);
		WPA_PUT_BE16(key->key_data_length, keydatalen);
	} else {
		wpa_printf(MSG_WARNING, "WPA: Unsupported key_info type %d",
			   ver);
		return -1;
	}
	wpa_hexdump_key(MSG_DEBUG, "WPA: decrypted EAPOL-Key key data",
			(u8 *) (key + 1), keydatalen);
	return 0;
}
Example #4
0
static u16 auth_shared_key(struct hostapd_data *hapd, struct sta_info *sta,
			   u16 auth_transaction, const u8 *challenge,
			   int iswep)
{
	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
		       HOSTAPD_LEVEL_DEBUG,
		       "authentication (shared key, transaction %d)",
		       auth_transaction);

	if (auth_transaction == 1) {
		if (!sta->challenge) {
			/* Generate a pseudo-random challenge */
			u8 key[8];
			time_t now;
			int r;
			sta->challenge = os_zalloc(WLAN_AUTH_CHALLENGE_LEN);
			if (sta->challenge == NULL)
				return WLAN_STATUS_UNSPECIFIED_FAILURE;

			now = time(NULL);
			r = random();
			os_memcpy(key, &now, 4);
			os_memcpy(key + 4, &r, 4);
			rc4_skip(key, sizeof(key), 0,
				 sta->challenge, WLAN_AUTH_CHALLENGE_LEN);
		}
		return 0;
	}

	if (auth_transaction != 3)
		return WLAN_STATUS_UNSPECIFIED_FAILURE;

	/* Transaction 3 */
	if (!iswep || !sta->challenge || !challenge ||
	    os_memcmp(sta->challenge, challenge, WLAN_AUTH_CHALLENGE_LEN)) {
		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
			       HOSTAPD_LEVEL_INFO,
			       "shared key authentication - invalid "
			       "challenge-response");
		return WLAN_STATUS_CHALLENGE_FAIL;
	}

	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
		       HOSTAPD_LEVEL_DEBUG,
		       "authentication OK (shared key)");
#ifdef IEEE80211_REQUIRE_AUTH_ACK
	/* Station will be marked authenticated if it ACKs the
	 * authentication reply. */
#else
	sta->flags |= WLAN_STA_AUTH;
	wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
#endif
	os_free(sta->challenge);
	sta->challenge = NULL;

	return 0;
}
Example #5
0
int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
                          u8 *plain, size_t len)
{
    size_t i, j, blocks;
    u8 tmp[32];

    switch (ctx->alg) {
    case CRYPTO_CIPHER_ALG_RC4:
        if (plain != crypt)
            os_memcpy(plain, crypt, len);
        rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen,
                 ctx->u.rc4.used_bytes, plain, len);
        ctx->u.rc4.used_bytes += len;
        break;
    case CRYPTO_CIPHER_ALG_AES:
        if (len % ctx->u.aes.block_size)
            return -1;
        blocks = len / ctx->u.aes.block_size;
        for (i = 0; i < blocks; i++) {
            os_memcpy(tmp, crypt, ctx->u.aes.block_size);
            aes_decrypt(ctx->u.aes.ctx_dec, crypt, plain);
            for (j = 0; j < ctx->u.aes.block_size; j++)
                plain[j] ^= ctx->u.aes.cbc[j];
            os_memcpy(ctx->u.aes.cbc, tmp, ctx->u.aes.block_size);
            plain += ctx->u.aes.block_size;
            crypt += ctx->u.aes.block_size;
        }
        break;
    case CRYPTO_CIPHER_ALG_3DES:
        if (len % 8)
            return -1;
        blocks = len / 8;
        for (i = 0; i < blocks; i++) {
            os_memcpy(tmp, crypt, 8);
            des3_decrypt(crypt, &ctx->u.des3.key, plain);
            for (j = 0; j < 8; j++)
                plain[j] ^= ctx->u.des3.cbc[j];
            os_memcpy(ctx->u.des3.cbc, tmp, 8);
            plain += 8;
            crypt += 8;
        }
        break;
    default:
        return -1;
    }

    return 0;
}
Example #6
0
static void entropy_init() {
    FILE *urandom = fopen("/dev/urandom", "r");
    if (urandom == NULL) {
        fprintf(stderr, "error: could not seed entropy pool\n");
        exit(EXIT_FAILURE); // emergency bailout
    }
    char seed[256];
    size_t count = sizeof(seed);
    while (count > 0) {
        count -= fread(&seed, 1, count, urandom);
    }
    fclose(urandom);
    rc4_init(&entropy_pool);
    rc4_schedule(&entropy_pool, seed, sizeof(seed));
    rc4_skip(&entropy_pool, 4096);
}
Example #7
0
/* Decrypt RSN EAPOL-Key key data (RC4 or AES-WRAP) */
static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm,
					   struct wpa_eapol_key *key, u16 ver)
{
	u16 keydatalen = WPA_GET_BE16(key->key_data_length);

	wpa_hexdump(MSG_DEBUG, "RSN: encrypted key data",(u8 *) (key + 1), keydatalen);
	if (!sm->ptk_set) //wpa_supplicant_verify_eapol_key_mic ÖÐÉèÖÃ
    {
		lwip_log("WPA: PTK not available, cannot decrypt EAPOL-Key key data.\n");
		return -1;
	}

	/* Decrypt key data here so that this operation does not need
	 * to be implemented separately for each message type. */
	if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4)
    {
		u8 ek[32];
		os_memcpy(ek, key->key_iv, 16);
		os_memcpy(ek + 16, sm->ptk.kek, 16);
		rc4_skip(ek, 32, 256, (u8 *) (key + 1), keydatalen);
	} 
    else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES)
    {
		u8 buf[512];
		if (keydatalen % 8)
        {
			lwip_log("WPA: Unsupported AES-WRAP len %d\n", keydatalen);
			return -1;
		}
		keydatalen -= 8; /* AES-WRAP adds 8 bytes */
		if (buf == NULL)
        {
			lwip_log("WPA: No memory for AES-UNWRAP buffer\n");
			return -1;
		}
		if (aes_unwrap(sm->ptk.kek, keydatalen / 8, (u8 *)(key + 1), buf))
	    {
			lwip_log("WPA: AES unwrap failed - could not decrypt EAPOL-Key key data\n");
			return -1;
		}
		os_memcpy(key + 1, buf, keydatalen);
		WPA_PUT_BE16(key->key_data_length, keydatalen);
	}
	wpa_hexdump_key(MSG_DEBUG, "WPA: decrypted EAPOL-Key key data", (u8*)(key + 1), keydatalen);
	
	return 0;
}
Example #8
0
void rc4hash(struct rc4hash *hash, const char *password) {
    struct rc4 rc4;
    rc4_init(&rc4);
    rc4_schedule(&rc4, (char *) &hash->salt, sizeof(hash->salt));

    /* Run scheduler 2^difficulty times. */
    char buffer[256];
    size_t length = strlen(password);
    memcpy(buffer, password, length);
    rc4_emit(&rc4, buffer + length, sizeof(buffer) - length);
    for (uint64_t i = 0; i < 1 << hash->difficulty; i++) {
        rc4_schedule(&rc4, buffer, sizeof(buffer));
    }

    /* Skip (2^difficulty-1)*64 bytes of output. */
    rc4_skip(&rc4, ((1 << hash->difficulty) - 1) * 64);

    /* Emit output. */
    rc4_emit(&rc4, hash->hash, RC4HASH_SIZE - RC4HASH_HEADER_SIZE);
}
Example #9
0
static u8 * decrypt_eapol_key_data_rc4(const u8 *kek,
				       const struct wpa_eapol_key *hdr,
				       size_t *len)
{
	u8 ek[32], *buf;
	u16 keydatalen = WPA_GET_BE16(hdr->key_data_length);

	buf = os_malloc(keydatalen);
	if (buf == NULL)
		return NULL;

	os_memcpy(ek, hdr->key_iv, 16);
	os_memcpy(ek + 16, kek, 16);
	os_memcpy(buf, hdr + 1, keydatalen);
	if (rc4_skip(ek, 32, 256, buf, keydatalen)) {
		wpa_printf(MSG_INFO, "RC4 failed");
		os_free(buf);
		return NULL;
	}

	*len = keydatalen;
	return buf;
}
Example #10
0
static void eapol_sm_processKey(struct eapol_sm *sm)
{
	struct ieee802_1x_hdr *hdr;
	struct ieee802_1x_eapol_key *key;
	struct eap_key_data keydata;
	u8 orig_key_sign[IEEE8021X_KEY_SIGN_LEN], datakey[32];
	u8 ekey[IEEE8021X_KEY_IV_LEN + IEEE8021X_ENCR_KEY_LEN];
	int key_len, res, sign_key_len, encr_key_len;
	u16 rx_key_length;

	wpa_printf(MSG_DEBUG, "EAPOL: processKey");
	if (sm->last_rx_key == NULL)
		return;

	if (!sm->conf.accept_802_1x_keys) {
		wpa_printf(MSG_WARNING, "EAPOL: Received IEEE 802.1X EAPOL-Key"
			   " even though this was not accepted - "
			   "ignoring this packet");
		return;
	}

	hdr = (struct ieee802_1x_hdr *) sm->last_rx_key;
	key = (struct ieee802_1x_eapol_key *) (hdr + 1);
	if (sizeof(*hdr) + be_to_host16(hdr->length) > sm->last_rx_key_len) {
		wpa_printf(MSG_WARNING, "EAPOL: Too short EAPOL-Key frame");
		return;
	}
	rx_key_length = WPA_GET_BE16(key->key_length);
	wpa_printf(MSG_DEBUG, "EAPOL: RX IEEE 802.1X ver=%d type=%d len=%d "
		   "EAPOL-Key: type=%d key_length=%d key_index=0x%x",
		   hdr->version, hdr->type, be_to_host16(hdr->length),
		   key->type, rx_key_length, key->key_index);

	eapol_sm_notify_lower_layer_success(sm, 1);
	sign_key_len = IEEE8021X_SIGN_KEY_LEN;
	encr_key_len = IEEE8021X_ENCR_KEY_LEN;
	res = eapol_sm_get_key(sm, (u8 *) &keydata, sizeof(keydata));
	if (res < 0) {
		wpa_printf(MSG_DEBUG, "EAPOL: Could not get master key for "
			   "decrypting EAPOL-Key keys");
		return;
	}
	if (res == 16) {
		/* LEAP derives only 16 bytes of keying material. */
		res = eapol_sm_get_key(sm, (u8 *) &keydata, 16);
		if (res) {
			wpa_printf(MSG_DEBUG, "EAPOL: Could not get LEAP "
				   "master key for decrypting EAPOL-Key keys");
			return;
		}
		sign_key_len = 16;
		encr_key_len = 16;
		os_memcpy(keydata.sign_key, keydata.encr_key, 16);
	} else if (res) {
		wpa_printf(MSG_DEBUG, "EAPOL: Could not get enough master key "
			   "data for decrypting EAPOL-Key keys (res=%d)", res);
		return;
	}

	/* The key replay_counter must increase when same master key */
	if (sm->replay_counter_valid &&
	    os_memcmp(sm->last_replay_counter, key->replay_counter,
		      IEEE8021X_REPLAY_COUNTER_LEN) >= 0) {
		wpa_printf(MSG_WARNING, "EAPOL: EAPOL-Key replay counter did "
			   "not increase - ignoring key");
		wpa_hexdump(MSG_DEBUG, "EAPOL: last replay counter",
			    sm->last_replay_counter,
			    IEEE8021X_REPLAY_COUNTER_LEN);
		wpa_hexdump(MSG_DEBUG, "EAPOL: received replay counter",
			    key->replay_counter, IEEE8021X_REPLAY_COUNTER_LEN);
		return;
	}

	/* Verify key signature (HMAC-MD5) */
	os_memcpy(orig_key_sign, key->key_signature, IEEE8021X_KEY_SIGN_LEN);
	os_memset(key->key_signature, 0, IEEE8021X_KEY_SIGN_LEN);
	hmac_md5(keydata.sign_key, sign_key_len,
		 sm->last_rx_key, sizeof(*hdr) + be_to_host16(hdr->length),
		 key->key_signature);
	if (os_memcmp(orig_key_sign, key->key_signature,
		      IEEE8021X_KEY_SIGN_LEN) != 0) {
		wpa_printf(MSG_DEBUG, "EAPOL: Invalid key signature in "
			   "EAPOL-Key packet");
		os_memcpy(key->key_signature, orig_key_sign,
			  IEEE8021X_KEY_SIGN_LEN);
		return;
	}
	wpa_printf(MSG_DEBUG, "EAPOL: EAPOL-Key key signature verified");

	key_len = be_to_host16(hdr->length) - sizeof(*key);
	if (key_len > 32 || rx_key_length > 32) {
		wpa_printf(MSG_WARNING, "EAPOL: Too long key data length %d",
			   key_len ? key_len : rx_key_length);
		return;
	}
	if (key_len == rx_key_length) {
		os_memcpy(ekey, key->key_iv, IEEE8021X_KEY_IV_LEN);
		os_memcpy(ekey + IEEE8021X_KEY_IV_LEN, keydata.encr_key,
			  encr_key_len);
		os_memcpy(datakey, key + 1, key_len);
		rc4_skip(ekey, IEEE8021X_KEY_IV_LEN + encr_key_len, 0,
			 datakey, key_len);
		wpa_hexdump_key(MSG_DEBUG, "EAPOL: Decrypted(RC4) key",
				datakey, key_len);
	} else if (key_len == 0) {
		/*
		 * IEEE 802.1X-2004 specifies that least significant Key Length
		 * octets from MS-MPPE-Send-Key are used as the key if the key
		 * data is not present. This seems to be meaning the beginning
		 * of the MS-MPPE-Send-Key. In addition, MS-MPPE-Send-Key in
		 * Supplicant corresponds to MS-MPPE-Recv-Key in Authenticator.
		 * Anyway, taking the beginning of the keying material from EAP
		 * seems to interoperate with Authenticators.
		 */
		key_len = rx_key_length;
		os_memcpy(datakey, keydata.encr_key, key_len);
		wpa_hexdump_key(MSG_DEBUG, "EAPOL: using part of EAP keying "
				"material data encryption key",
				datakey, key_len);
	} else {
		wpa_printf(MSG_DEBUG, "EAPOL: Invalid key data length %d "
			   "(key_length=%d)", key_len, rx_key_length);
		return;
	}

	sm->replay_counter_valid = TRUE;
	os_memcpy(sm->last_replay_counter, key->replay_counter,
		  IEEE8021X_REPLAY_COUNTER_LEN);

	wpa_printf(MSG_DEBUG, "EAPOL: Setting dynamic WEP key: %s keyidx %d "
		   "len %d",
		   key->key_index & IEEE8021X_KEY_INDEX_FLAG ?
		   "unicast" : "broadcast",
		   key->key_index & IEEE8021X_KEY_INDEX_MASK, key_len);

	if (sm->ctx->set_wep_key &&
	    sm->ctx->set_wep_key(sm->ctx->ctx,
				 key->key_index & IEEE8021X_KEY_INDEX_FLAG,
				 key->key_index & IEEE8021X_KEY_INDEX_MASK,
				 datakey, key_len) < 0) {
		wpa_printf(MSG_WARNING, "EAPOL: Failed to set WEP key to the "
			   " driver.");
	} else {
		if (key->key_index & IEEE8021X_KEY_INDEX_FLAG)
			sm->unicast_key_received = TRUE;
		else
			sm->broadcast_key_received = TRUE;

		if ((sm->unicast_key_received ||
		     !(sm->conf.required_keys & EAPOL_REQUIRE_KEY_UNICAST)) &&
		    (sm->broadcast_key_received ||
		     !(sm->conf.required_keys & EAPOL_REQUIRE_KEY_BROADCAST)))
		{
			wpa_printf(MSG_DEBUG, "EAPOL: all required EAPOL-Key "
				   "frames received");
			sm->portValid = TRUE;
			if (sm->ctx->eapol_done_cb)
				sm->ctx->eapol_done_cb(sm->ctx->ctx);
		}
	}
}
int  fast_crypto_cipher_decrypt(struct crypto_cipher *ctx, const uint8_t *crypt,
			  uint8_t *plain, size_t len)
{
    size_t i, j, blocks;
    uint8_t tmp[32];
    struct fast_crypto_cipher *fast_ctx;

    fast_ctx = (struct fast_crypto_cipher *)ctx;
    
    switch (fast_ctx->alg) {
        case CRYPTO_CIPHER_ALG_RC4:
            if (plain != crypt) {
                os_memcpy(plain, crypt, len);
            }
            rc4_skip(fast_ctx->u.rc4.key, fast_ctx->u.rc4.keylen,
            fast_ctx->u.rc4.used_bytes, plain, len);
            fast_ctx->u.rc4.used_bytes += len;
            break;
        case CRYPTO_CIPHER_ALG_AES:
            if (len % AES_BLOCK_SIZE) {
                return -1;
            }
            blocks = len / AES_BLOCK_SIZE;
            for (i = 0; i < blocks; i++) {
                os_memcpy(tmp, crypt, AES_BLOCK_SIZE);
                mbedtls_aes_decrypt(&(fast_ctx->u.aes.ctx_dec), crypt, plain);
                for (j = 0; j < AES_BLOCK_SIZE; j++)
                    plain[j] ^= fast_ctx->u.aes.cbc[j];
                os_memcpy(fast_ctx->u.aes.cbc, tmp, AES_BLOCK_SIZE);
                plain += AES_BLOCK_SIZE;
                crypt += AES_BLOCK_SIZE;
            }
            break;
#ifdef CONFIG_DES3
        case CRYPTO_CIPHER_ALG_3DES:
            if (len % 8) {
                return -1;
            }
            blocks = len / 8;
            for (i = 0; i < blocks; i++) {
                os_memcpy(tmp, crypt, 8);
                des3_decrypt(crypt, &fast_ctx->u.des3.key, plain);
                for (j = 0; j < 8; j++) {
                    plain[j] ^= fast_ctx->u.des3.cbc[j];
                }
                os_memcpy(fast_ctx->u.des3.cbc, tmp, 8);
                plain += 8;
                crypt += 8;
            }
            break;
#endif
#ifdef CONFIG_DES
        case CRYPTO_CIPHER_ALG_DES:
            if (len % 8) {
                return -1;
            }
            blocks = len / 8;
            for (i = 0; i < blocks; i++) {
                os_memcpy(tmp, crypt, 8);
                des_block_decrypt(crypt, fast_ctx->u.des.dk, plain);
                for (j = 0; j < 8; j++) {
                    plain[j] ^= fast_ctx->u.des.cbc[j];
                }
                os_memcpy(fast_ctx->u.des.cbc, tmp, 8);
                plain += 8;
                crypt += 8;
            }
            break;
#endif
        default:
            return -1;
}

return 0;
}
Example #12
0
/**
 * cckm_egtk_to_gtk - Calculate GTK from Encrypted GTK
 * @cckm_rn: Association Request Numner
 * @gtk: Length of BTK
 * @gtk_len: Length of GTK
 *
 * GTK = RC4(RN | PTK-802.1X-Encrypt-Key, EGTK)
 * GTK = AES-Keywrap(PTK-802.1X-Encrypt-Key, EGTK)
 * - where PTK-802.1X-Encrypt-Key is the key as defined in Section 0
 * - Note that while the IV is not transmitted in the clear, its encrypted
 *   value is included in the EGTK. Thus, the EGTK length shall be the GTK
 *   key length plus 8 octets (e.g. the IV length). More explicitly, if the
 *   broadcast cipher is TKIP, while the GTK is 32 octets, the EGTK shall
 *   be 40 octets; similarly for AESCCMP, the GTK is 16 octets while the
 *   EGTK shall be 24 octets.
 */
static int cckm_install_gtk(struct wpa_sm *sm, u32 cckm_rn, u8 *gtk,
		int gtk_len, int keyidx, const u8 *key_rsc, int key_rsc_len)
{
	u8 gtk_buf[32];
	enum wpa_alg alg;

	switch (sm->group_cipher) {
		case WPA_CIPHER_CCMP:
			alg = WPA_ALG_CCMP;
			break;
		case WPA_CIPHER_TKIP:
			alg = WPA_ALG_TKIP;
			break;
		case WPA_CIPHER_NONE:
			wpa_printf(MSG_DEBUG, "WPA: Pairwise Cipher Suite: "
					"NONE - do not use pairwise keys");
			return 0;
		default:
			wpa_printf(MSG_WARNING, "WPA: Unsupported pairwise cipher %d",
					sm->pairwise_cipher);
			return -1;
	}

	if (sm->group_cipher == WPA_CIPHER_CCMP) {
		gtk_len -= 8;
		if (aes_unwrap(sm->ptk.kek, gtk_len / 8, gtk, gtk_buf)) {
			wpa_printf(MSG_WARNING, "WPA: AES unwrap "
					"failed - could not decrypt GTK");
			return -1;
		}
		gtk = gtk_buf;
	} else if (sm->group_cipher == WPA_CIPHER_TKIP) {
		u8 data[20];

		WPA_PUT_LE32(data, cckm_rn);
		os_memcpy(data + 4, &sm->ptk.kek, sizeof(sm->ptk.kek));
		wpa_hexdump_key(MSG_DEBUG, "EGTK-Data", data, sizeof(data));

		rc4_skip(data, sizeof(data), 256, gtk, gtk_len);

		/* Swap Tx/Rx keys for Michael MIC */
		os_memcpy(gtk_buf, gtk, 16);
		os_memcpy(gtk_buf + 16, gtk + 24, 8);
		os_memcpy(gtk_buf + 24, gtk + 16, 8);
		gtk = gtk_buf;
	}

	wpa_hexdump_key(MSG_DEBUG, "WPA: Group Key", gtk, gtk_len);
	wpa_printf(MSG_DEBUG, "WPA: Installing GTK to the driver "
			"(keyidx=%d tx=%d len=%d).", keyidx, 0, gtk_len);
	wpa_hexdump(MSG_DEBUG, "WPA: RSC", key_rsc, key_rsc_len);

	if (wpa_sm_set_key(sm, alg, (u8 *) "\xff\xff\xff\xff\xff\xff",
				keyidx, 0, key_rsc, key_rsc_len,
				gtk, gtk_len) < 0) {
		wpa_printf(MSG_WARNING, "WPA: Failed to set GTK to "
				"the driver.");
		return -1;
	}

	return 0;
}
int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
			  u8 *crypt, size_t len)
{
	size_t i, j, blocks;

	switch (ctx->alg) {
	case CRYPTO_CIPHER_ALG_RC4:
		if (plain != crypt)
			os_memcpy(crypt, plain, len);
		rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen,
			 ctx->u.rc4.used_bytes, crypt, len);
		ctx->u.rc4.used_bytes += len;
		break;
	case CRYPTO_CIPHER_ALG_AES:
		if (len % AES_BLOCK_SIZE)
			return -1;
		blocks = len / AES_BLOCK_SIZE;
		for (i = 0; i < blocks; i++) {
			for (j = 0; j < AES_BLOCK_SIZE; j++)
				ctx->u.aes.cbc[j] ^= plain[j];
			aes_encrypt(ctx->u.aes.ctx_enc, ctx->u.aes.cbc,
				    ctx->u.aes.cbc);
			os_memcpy(crypt, ctx->u.aes.cbc, AES_BLOCK_SIZE);
			plain += AES_BLOCK_SIZE;
			crypt += AES_BLOCK_SIZE;
		}
		break;
	case CRYPTO_CIPHER_ALG_3DES:
		if (len % 8)
			return -1;
		blocks = len / 8;
		for (i = 0; i < blocks; i++) {
			for (j = 0; j < 8; j++)
				ctx->u.des3.cbc[j] ^= plain[j];
			des3_encrypt(ctx->u.des3.cbc, &ctx->u.des3.key,
				     ctx->u.des3.cbc);
			os_memcpy(crypt, ctx->u.des3.cbc, 8);
			plain += 8;
			crypt += 8;
		}
		break;
	case CRYPTO_CIPHER_ALG_DES:
		if (len % 8)
			return -1;
		blocks = len / 8;
		for (i = 0; i < blocks; i++) {
			for (j = 0; j < 8; j++)
				ctx->u.des3.cbc[j] ^= plain[j];
			des_block_encrypt(ctx->u.des.cbc, ctx->u.des.ek,
					  ctx->u.des.cbc);
			os_memcpy(crypt, ctx->u.des.cbc, 8);
			plain += 8;
			crypt += 8;
		}
		break;
	default:
		return -1;
	}

	return 0;
}
Example #14
0
/**
 * rc4 - XOR RC4 stream to given data
 * @buf: data to be XOR'ed with RC4 stream
 * @len: buf length
 * @key: RC4 key
 * @key_len: RC4 key length
 *
 * Generate RC4 pseudo random stream for the given key and XOR this with the
 * data buffer to perform RC4 encryption/decryption.
 */
void rc4(u8 *buf, size_t len, const u8 *key, size_t key_len)
{
	rc4_skip(key, key_len, 0, buf, len);
}
Example #15
0
static int wpa_supplicant_process_1_of_2_wpa(struct wpa_sm *sm,
					     const struct wpa_eapol_key *key,
					     size_t keydatalen, int key_info,
					     size_t extra_len, u16 ver,
					     struct wpa_gtk_data *gd)
{
	size_t maxkeylen;
	u8 ek[32];

	gd->gtk_len = WPA_GET_BE16(key->key_length);
	maxkeylen = keydatalen;
	if (keydatalen > extra_len) {
		wpa_printf(MSG_INFO, "WPA: Truncated EAPOL-Key packet:"
			   " key_data_length=%lu > extra_len=%lu",
			   (unsigned long) keydatalen,
			   (unsigned long) extra_len);
		return -1;
	}
	if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
		if (maxkeylen < 8) {
			wpa_printf(MSG_INFO, "WPA: Too short maxkeylen (%lu)",
				   (unsigned long) maxkeylen);
			return -1;
		}
		maxkeylen -= 8;
	}

	if (wpa_supplicant_check_group_cipher(sm->group_cipher,
					      gd->gtk_len, maxkeylen,
					      &gd->key_rsc_len, &gd->alg))
		return -1;

	gd->keyidx = (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >>
		WPA_KEY_INFO_KEY_INDEX_SHIFT;
	if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4) {
		os_memcpy(ek, key->key_iv, 16);
		os_memcpy(ek + 16, sm->ptk.kek, 16);
		if (keydatalen > sizeof(gd->gtk)) {
			wpa_printf(MSG_WARNING, "WPA: RC4 key data "
				   "too long (%lu)",
				   (unsigned long) keydatalen);
			return -1;
		}
		os_memcpy(gd->gtk, key + 1, keydatalen);
		if (rc4_skip(ek, 32, 256, gd->gtk, keydatalen)) {
			wpa_printf(MSG_ERROR, "WPA: RC4 failed");
			return -1;
		}
	} else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
		if (keydatalen % 8) {
			wpa_printf(MSG_WARNING, "WPA: Unsupported AES-WRAP "
				   "len %lu", (unsigned long) keydatalen);
			return -1;
		}
		if (maxkeylen > sizeof(gd->gtk)) {
			wpa_printf(MSG_WARNING, "WPA: AES-WRAP key data "
				   "too long (keydatalen=%lu maxkeylen=%lu)",
				   (unsigned long) keydatalen,
				   (unsigned long) maxkeylen);
			return -1;
		}
		if (aes_unwrap(sm->ptk.kek, maxkeylen / 8,
			       (const u8 *) (key + 1), gd->gtk)) {
			wpa_printf(MSG_WARNING, "WPA: AES unwrap "
				   "failed - could not decrypt GTK");
			return -1;
		}
	} else {
		wpa_printf(MSG_WARNING, "WPA: Unsupported key_info type %d",
			   ver);
		return -1;
	}
	gd->tx = wpa_supplicant_gtk_tx_bit_workaround(
		sm, !!(key_info & WPA_KEY_INFO_TXRX));
	return 0;
}