aboutsummaryrefslogtreecommitdiffstats
path: root/epan
diff options
context:
space:
mode:
authorMikael Kanstrup <mikael.kanstrup@sony.com>2018-11-08 14:30:40 +0100
committerAnders Broman <a.broman58@gmail.com>2018-11-09 05:51:22 +0000
commit54c966b986ddc9b054436010606e29c4304a968e (patch)
tree44ccb66316b1166c581e01df1254d4819e5f6dbe /epan
parent8c9f09bf34d303d5a53014c023d24ec1c0cad954 (diff)
dot11decrypt: Create RC4 decryption and key copy helper functions
In preparation for decrypting and dissecting EAPOL keydata in ieee80211 dissector move the RC4 decryption and key copy into separate helper functions. Change-Id: I13f3e981038f48526032e263b6eb3c9e3496abbe Reviewed-on: https://code.wireshark.org/review/30546 Petri-Dish: Anders Broman <a.broman58@gmail.com> Tested-by: Petri Dish Buildbot Reviewed-by: Anders Broman <a.broman58@gmail.com>
Diffstat (limited to 'epan')
-rw-r--r--epan/crypt/dot11decrypt.c104
-rw-r--r--epan/crypt/dot11decrypt_rijndael.c2
-rw-r--r--epan/crypt/dot11decrypt_rijndael.h2
3 files changed, 62 insertions, 46 deletions
diff --git a/epan/crypt/dot11decrypt.c b/epan/crypt/dot11decrypt.c
index 225b0ea6dd..3ff5449025 100644
--- a/epan/crypt/dot11decrypt.c
+++ b/epan/crypt/dot11decrypt.c
@@ -285,13 +285,56 @@ typedef struct {
/* Minimum possible group key msg size (group key msg using CCMP as cipher)*/
#define GROUP_KEY_PAYLOAD_LEN_MIN sizeof(EAPOL_RSN_KEY) + GROUP_KEY_MIN_LEN
+static void
+Dot11DecryptCopyKey(PDOT11DECRYPT_SEC_ASSOCIATION sa, PDOT11DECRYPT_KEY_ITEM key)
+{
+ if (key!=NULL) {
+ if (sa->key!=NULL)
+ memcpy(key, sa->key, sizeof(DOT11DECRYPT_KEY_ITEM));
+ else
+ memset(key, 0, sizeof(DOT11DECRYPT_KEY_ITEM));
+ memcpy(key->KeyData.Wpa.Ptk, sa->wpa.ptk, DOT11DECRYPT_WPA_PTK_LEN);
+ if (sa->wpa.key_ver==DOT11DECRYPT_WPA_KEY_VER_NOT_CCMP)
+ key->KeyType=DOT11DECRYPT_KEY_TYPE_TKIP;
+ else if (sa->wpa.key_ver==DOT11DECRYPT_WPA_KEY_VER_AES_CCMP)
+ key->KeyType=DOT11DECRYPT_KEY_TYPE_CCMP;
+ }
+}
+
+static guint8*
+Dot11DecryptRc4KeyData(const guint8 *decryption_key, guint decryption_key_len,
+ const guint8 *encrypted_keydata, guint encrypted_keydata_len)
+{
+ gcry_cipher_hd_t rc4_handle;
+ guint8 dummy[256] = { 0 };
+ guint8 *decrypted_key = NULL;
+
+ if (gcry_cipher_open (&rc4_handle, GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM, 0)) {
+ return NULL;
+ }
+ if (gcry_cipher_setkey(rc4_handle, decryption_key, decryption_key_len)) {
+ gcry_cipher_close(rc4_handle);
+ return NULL;
+ }
+ decrypted_key = (guint8 *)g_memdup(encrypted_keydata, encrypted_keydata_len);
+ if (!decrypted_key) {
+ return NULL;
+ }
+
+ /* Do dummy 256 iterations of the RC4 algorithm (per 802.11i, Draft 3.0, p. 97 line 6) */
+ gcry_cipher_decrypt(rc4_handle, dummy, 256, NULL, 0);
+ gcry_cipher_decrypt(rc4_handle, decrypted_key, encrypted_keydata_len, NULL, 0);
+ gcry_cipher_close(rc4_handle);
+ return decrypted_key;
+}
+
/* XXX - what if this doesn't get the key? */
static INT
Dot11DecryptDecryptWPABroadcastKey(const EAPOL_RSN_KEY *pEAPKey, guint8 *decryption_key, PDOT11DECRYPT_SEC_ASSOCIATION sa, guint eapol_len)
{
guint8 key_version;
const guint8 *key_data;
- guint8 *szEncryptedKey;
+ guint8 *decrypted_key = NULL;
guint16 key_bytes_len = 0; /* Length of the total key data field */
guint16 key_len; /* Actual group key length */
static DOT11DECRYPT_KEY_ITEM dummy_key; /* needed in case Dot11DecryptRsnaMng() wants the key structure */
@@ -323,9 +366,8 @@ Dot11DecryptDecryptWPABroadcastKey(const EAPOL_RSN_KEY *pEAPKey, guint8 *decrypt
/* Encrypted key is in the information element field of the EAPOL key packet */
key_data = (const guint8 *)pEAPKey + sizeof(EAPOL_RSN_KEY);
- szEncryptedKey = (guint8 *)g_memdup(key_data, key_bytes_len);
- DEBUG_DUMP("Encrypted Broadcast key:", szEncryptedKey, key_bytes_len);
+ DEBUG_DUMP("Encrypted Broadcast key:", key_data, key_bytes_len);
DEBUG_DUMP("KeyIV:", pEAPKey->key_iv, 16);
DEBUG_DUMP("decryption_key:", decryption_key, 16);
@@ -342,13 +384,10 @@ Dot11DecryptDecryptWPABroadcastKey(const EAPOL_RSN_KEY *pEAPKey, guint8 *decrypt
/* for to determine the true key length, and thus the group cipher. */
if (key_version == DOT11DECRYPT_WPA_KEY_VER_NOT_CCMP){
- guint8 new_key[32];
- guint8 dummy[256] = { 0 };
/* TKIP key */
/* Per 802.11i, Draft 3.0 spec, section 8.5.2, p. 97, line 4-8, */
/* group key is decrypted using RC4. Concatenate the IV with the 16 byte EK (PTK+16) to get the decryption key */
-
- gcry_cipher_hd_t rc4_handle;
+ guint8 new_key[32];
/* The WPA group key just contains the GTK bytes so deducing the type is straightforward */
/* Note - WPA M3 doesn't contain a group key so we'll only be here for the group handshake */
@@ -358,22 +397,10 @@ Dot11DecryptDecryptWPABroadcastKey(const EAPOL_RSN_KEY *pEAPKey, guint8 *decrypt
memcpy(new_key, pEAPKey->key_iv, 16);
memcpy(new_key+16, decryption_key, 16);
DEBUG_DUMP("FullDecrKey:", new_key, 32);
-
- if (gcry_cipher_open (&rc4_handle, GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM, 0)) {
- g_free(szEncryptedKey);
- return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
- }
- if (gcry_cipher_setkey(rc4_handle, new_key, sizeof(new_key))) {
- gcry_cipher_close(rc4_handle);
- g_free(szEncryptedKey);
- return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
+ decrypted_key = Dot11DecryptRc4KeyData(new_key, 32, key_data, key_bytes_len);
+ if (!decrypted_key) {
+ return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
}
-
- /* Do dummy 256 iterations of the RC4 algorithm (per 802.11i, Draft 3.0, p. 97 line 6) */
- gcry_cipher_decrypt(rc4_handle, dummy, 256, NULL, 0);
- gcry_cipher_decrypt(rc4_handle, szEncryptedKey, key_bytes_len, NULL, 0);
- gcry_cipher_close(rc4_handle);
-
} else if (key_version == DOT11DECRYPT_WPA_KEY_VER_AES_CCMP){
/* AES CCMP key */
@@ -383,7 +410,10 @@ Dot11DecryptDecryptWPABroadcastKey(const EAPOL_RSN_KEY *pEAPKey, guint8 *decrypt
guint8 *decrypted_data;
/* Unwrap the key; the result is key_bytes_len in length */
- decrypted_data = AES_unwrap(decryption_key, 16, szEncryptedKey, key_bytes_len);
+ decrypted_data = AES_unwrap(decryption_key, 16, key_data, key_bytes_len);
+ if (!decrypted_data) {
+ return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
+ }
/* With WPA2 what we get after Broadcast Key decryption is an actual RSN structure.
The key itself is stored as a GTK KDE
@@ -416,7 +446,6 @@ Dot11DecryptDecryptWPABroadcastKey(const EAPOL_RSN_KEY *pEAPKey, guint8 *decrypt
if (key_found){
if (decrypted_data[key_index+1] <= 6) {
g_free(decrypted_data);
- g_free(szEncryptedKey);
return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
}
key_length = decrypted_data[key_index+1] - 6;
@@ -424,15 +453,14 @@ Dot11DecryptDecryptWPABroadcastKey(const EAPOL_RSN_KEY *pEAPKey, guint8 *decrypt
if (key_index+8 >= key_bytes_len ||
key_length > key_bytes_len - key_index - 8) {
g_free(decrypted_data);
- g_free(szEncryptedKey);
return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
}
/* Skip over the GTK header info, and don't copy past the end of the encrypted data */
- memcpy(szEncryptedKey, decrypted_data+key_index+8, key_length);
+ decrypted_key = (guint8 *)g_memdup(decrypted_data+key_index+8, key_length);
+ g_free(decrypted_data);
} else {
g_free(decrypted_data);
- g_free(szEncryptedKey);
return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
}
@@ -440,19 +468,17 @@ Dot11DecryptDecryptWPABroadcastKey(const EAPOL_RSN_KEY *pEAPKey, guint8 *decrypt
sa->wpa.key_ver = DOT11DECRYPT_WPA_KEY_VER_NOT_CCMP;
else
sa->wpa.key_ver = DOT11DECRYPT_WPA_KEY_VER_AES_CCMP;
-
- g_free(decrypted_data);
}
key_len = (sa->wpa.key_ver==DOT11DECRYPT_WPA_KEY_VER_NOT_CCMP)?TKIP_GROUP_KEY_LEN:CCMP_GROUP_KEY_LEN;
if (key_len > key_bytes_len) {
/* the key required for this protocol is longer than the key that we just calculated */
- g_free(szEncryptedKey);
+ g_free(decrypted_key);
return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
}
/* Decrypted key is now in szEncryptedKey with len of key_len */
- DEBUG_DUMP("Broadcast key:", szEncryptedKey, key_len);
+ DEBUG_DUMP("Broadcast key:", decrypted_key, key_len);
/* Load the proper key material info into the SA */
sa->key = &dummy_key; /* we just need key to be not null because it is checked in Dot11DecryptRsnaMng(). The WPA key materials are actually in the .wpa structure */
@@ -461,8 +487,8 @@ Dot11DecryptDecryptWPABroadcastKey(const EAPOL_RSN_KEY *pEAPKey, guint8 *decrypt
/* Since this is a GTK and its size is only 32 bytes (vs. the 64 byte size of a PTK), we fake it and put it in at a 32-byte offset so the */
/* Dot11DecryptRsnaMng() function will extract the right piece of the GTK for decryption. (The first 16 bytes of the GTK are used for decryption.) */
memset(sa->wpa.ptk, 0, sizeof(sa->wpa.ptk));
- memcpy(sa->wpa.ptk+32, szEncryptedKey, key_len);
- g_free(szEncryptedKey);
+ memcpy(sa->wpa.ptk+32, decrypted_key, key_len);
+ g_free(decrypted_key);
return DOT11DECRYPT_RET_SUCCESS_HANDSHAKE;
}
@@ -1222,17 +1248,7 @@ Dot11DecryptRsnaMng(
*decrypt_len-=8;
memmove(decrypt_data+offset, decrypt_data+offset+8, *decrypt_len-offset);
- if (key!=NULL) {
- if (sa->key!=NULL)
- memcpy(key, sa->key, sizeof(DOT11DECRYPT_KEY_ITEM));
- else
- memset(key, 0, sizeof(DOT11DECRYPT_KEY_ITEM));
- memcpy(key->KeyData.Wpa.Ptk, sa->wpa.ptk, DOT11DECRYPT_WPA_PTK_LEN); /* copy the PTK to the key structure for future use by wireshark */
- if (sa->wpa.key_ver==DOT11DECRYPT_WPA_KEY_VER_NOT_CCMP)
- key->KeyType=DOT11DECRYPT_KEY_TYPE_TKIP;
- else if (sa->wpa.key_ver==DOT11DECRYPT_WPA_KEY_VER_AES_CCMP)
- key->KeyType=DOT11DECRYPT_KEY_TYPE_CCMP;
- }
+ Dot11DecryptCopyKey(sa, key);
return DOT11DECRYPT_RET_SUCCESS;
}
diff --git a/epan/crypt/dot11decrypt_rijndael.c b/epan/crypt/dot11decrypt_rijndael.c
index 7eb3d530ec..9488f991da 100644
--- a/epan/crypt/dot11decrypt_rijndael.c
+++ b/epan/crypt/dot11decrypt_rijndael.c
@@ -36,7 +36,7 @@ This function is used to unwrap an encrypted AES key. One example of its use is
in the WPA-2 protocol to get the group key.
*/
UCHAR *
-AES_unwrap(UCHAR *kek, UINT16 key_len, UCHAR *cipher_text, UINT16 cipher_len)
+AES_unwrap(const UCHAR *kek, UINT16 key_len, const UCHAR *cipher_text, UINT16 cipher_len)
{
UCHAR *output;
UCHAR a[8], b[16];
diff --git a/epan/crypt/dot11decrypt_rijndael.h b/epan/crypt/dot11decrypt_rijndael.h
index 64bc351660..f653d205fd 100644
--- a/epan/crypt/dot11decrypt_rijndael.h
+++ b/epan/crypt/dot11decrypt_rijndael.h
@@ -38,7 +38,7 @@
/******************************************************************************/
/* Type definitions */
/* */
-UCHAR *AES_unwrap(UCHAR *kek, UINT16 key_len, UCHAR *cipher_text, UINT16 cipher_len);
+UCHAR *AES_unwrap(const UCHAR *kek, UINT16 key_len, const UCHAR *cipher_text, UINT16 cipher_len);
/* */
/******************************************************************************/