public byte[] calc_pmk(byte[] key) throws NoSuchAlgorithmException, InvalidKeyException {
		try {
			MessageDigest ipad = MessageDigest.getInstance("SHA-1");
			MessageDigest opad = MessageDigest.getInstance("SHA-1");

			int keyCutoff = Math.min(key.length, 64);

			for (int i = 0; i < keyCutoff; i++) {
				ipad.update((byte)(key[i] ^ 0x36));
				opad.update((byte)(key[i] ^ 0x5c));
			}
			for (int i = keyCutoff; i < 64; i++) {
				ipad.update((byte)0x36);
				opad.update((byte)0x5c);
			}

			byte[] pmk = new byte[40];

			sha1Mac.init(new SecretKeySpec(key, "HmacSHA1"));

			byte[] essid = Arrays.copyOf(this.apInfo.essid, this.apInfo.essid.length + 4);

			essid[essid.length - 1] = 1;
			sha1Mac.update(essid);
			sha1Mac.doFinal(pmk, 0);

			byte[] buffer = Arrays.copyOf(pmk, 20);

			// TODO: replace with PBKDF2?
			for (int i = 4094; i >= 0; i--) {
				MessageDigest temp;

				temp = (MessageDigest)ipad.clone();
				temp.update(buffer);
				temp.digest(buffer, 0, buffer.length);

				temp = (MessageDigest)opad.clone();
				temp.update(buffer);
				temp.digest(buffer, 0, buffer.length);

				for (int j = buffer.length - 1; j >= 0; j--) {
					pmk[j] ^= buffer[j];
				}
			}


			essid[essid.length - 1] = 2;
			sha1Mac.update(essid);
			sha1Mac.doFinal(pmk, 20);
			buffer = Arrays.copyOfRange(pmk, 20, 40);

			// TODO: replace with PBKDF2?
			for (int i = 4094; i >= 0; i--) {
				MessageDigest temp;

				temp = (MessageDigest)ipad.clone();
				temp.update(buffer);
				temp.digest(buffer, 0, buffer.length);

				temp = (MessageDigest)opad.clone();
				temp.update(buffer);
				temp.digest(buffer, 0, buffer.length);

				for (int j = buffer.length - 1; j >= 0; j--) {
					pmk[j + 20] ^= buffer[j];
				}
			}


			return pmk;
		} catch (ShortBufferException e) {
			throw new RuntimeException();
		} catch (CloneNotSupportedException e) {
			// FIXME:
			throw new RuntimeException();
		} catch (DigestException e) {
			// TODO Auto-generated catch block
			throw new RuntimeException();
		}
	}