How to calculate PMKID for WPA*01?
#3
Attached (quick and dirty) sample code (hash is taken from hashcat example hashes (22000).

Code:
$ ./evp
PMKID expected:   4d4fe7aac3a2cecab195321ceb99a7d0
PMKID calculated: 4d4fe7aac3a2cecab195321ceb99a7d0

Please notice that we are using the new EVP API:
https://wiki.openssl.org/index.php/OpenSSL_3.0


Code:
//essid (networkname)....: hashcat-essid
//password...............: hashcat!
//plainmasterkey (SHA1)..: 88f43854ae7b1624fc2ab7724859e795130f4843c7535729e819cf92f39535dc

//4d4fe7aac3a2cecab195321ceb99a7d0:fc690c158264:f4747f87f9f4:hashcat-essid:hashcat!

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#include <stdbool.h>

#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/params.h>


/*===========================================================================*/
// global EVP var
static EVP_MAC *hmac;
static EVP_MAC *cmac;
static EVP_MAC_CTX *ctxhmac = NULL;
static EVP_MAC_CTX *ctxcmac = NULL;
static OSSL_PARAM paramsmd5[3];
static OSSL_PARAM paramssha1[3];
static OSSL_PARAM paramsaes128[3];
/*===========================================================================*/

/*===========================================================================*/
static bool evpinitwpa()
{
hmac = EVP_MAC_fetch(NULL, "hmac", NULL);
if(hmac == NULL) return false;
cmac = EVP_MAC_fetch(NULL, "cmac", NULL);
if(cmac == NULL) return false;

paramsmd5[0] = OSSL_PARAM_construct_utf8_string("digest", "md5", 0);
paramsmd5[1] = OSSL_PARAM_construct_end();

paramssha1[0] = OSSL_PARAM_construct_utf8_string("digest", "sha1", 0);
paramssha1[1] = OSSL_PARAM_construct_end();

paramsaes128[0] = OSSL_PARAM_construct_utf8_string("cipher", "aes-128-cbc", 0);
paramsaes128[1] = OSSL_PARAM_construct_end();

ctxhmac = EVP_MAC_CTX_new(hmac);
if(ctxhmac == NULL) return false;
ctxcmac = EVP_MAC_CTX_new(cmac);
if(ctxcmac == NULL) return false;
return true;
}
/*===========================================================================*/
static bool genpmkid(const unsigned char *pmk, uint8_t *macap, uint8_t *macclient, uint8_t *pmkid)
{
static char *pmkname = "PMK Name";

memcpy(pmkid, pmkname, 8);
memcpy(pmkid +8, macap, 6);
memcpy(pmkid +14, macclient, 6);
if(!EVP_MAC_init(ctxhmac, pmk, 32, paramssha1)) return false;
if(!EVP_MAC_update(ctxhmac, pmkid, 20)) return false;
if(!EVP_MAC_final(ctxhmac, pmkid, NULL, 20)) return false;
return true;
}
/*===========================================================================*/

int main()
{
static uint8_t macap[] = {0xfc, 0x69, 0x0c, 0x15, 0x82, 0x64};
static uint8_t macclient[] = {0xf4, 0x74, 0x7f, 0x87, 0xf9, 0xf4};
static uint8_t pmk[] =
{
0x88, 0xf4, 0x38, 0x54, 0xae, 0x7b, 0x16, 0x24, 0xfc, 0x2a, 0xb7, 0x72, 0x48, 0x59, 0xe7, 0x95,
0x13, 0x0f, 0x48, 0x43, 0xc7, 0x53, 0x57, 0x29, 0xe8, 0x19, 0xcf, 0x92, 0xf3, 0x95, 0x35, 0xdc
};

static uint8_t pmkid[20];

if(evpinitwpa() == false) goto err;
size_t i;

if(genpmkid(pmk, macap, macclient, pmkid) == false) goto err;

printf("PMKID expected:   4d4fe7aac3a2cecab195321ceb99a7d0\nPMKID calculated: ");
for (i = 0; i < 16; i++) printf("%02x", pmkid[i]);
printf("\n");

EVP_MAC_CTX_free(ctxhmac);
EVP_MAC_free(hmac);
exit(0);

err:
EVP_MAC_CTX_free(ctxhmac);
EVP_MAC_free(hmac);
fprintf(stderr, "Something went wrong\n");
ERR_print_errors_fp(stderr);
exit (1);
}

Please notice:
The code include EVP init code of WPA1, WPA2 and WPA2 key version 3 while the PTK and MIC calculation is still missing. But this is simple to add (when using the new EVP API).

From my point of view it is worth to move from OpenSSL 1.1 to 3.0 (for many reasons), but I have to rewrite the entire crypto stuff of hcxdumptool, hcxtools and hcxkeys to get benefit of the new EVP API.
Reply


Messages In This Thread
How to calculate PMKID for WPA*01? - by Caster - 10-16-2022, 12:16 PM
RE: How to calculate PMKID for WPA*01? - by ZerBea - 11-10-2022, 06:16 PM