Forráskód Böngészése

qcacmn: Add FILS crypto API for rIK generation

Replace the lim_default_hmac_sha256_kdf() & lim_create_fils_rik()
API  with crypto API since both these API are primarily for
cryptographic derivation of re-authentication integrity key(rIK)

Use the new crypto APIs qdf_default_hmac_sha256_kdf(),
wlan_crypto_create_fils_rik() for this.

Change-Id: I1c8f38ee0124b8b3eb527d4b01d39add134e181b
CRs-Fixed: 2752635
Pragaspathi Thilagaraj 4 éve
szülő
commit
0df12365ac

+ 30 - 0
qdf/inc/qdf_crypto.h

@@ -54,6 +54,8 @@ extern "C" {
 #define IS_VALID_CTR_KEY_LEN(len) ((((len) == 16) || ((len) == 32) || \
 	((len) == 48)) ? 1 : 0)
 
+#define WLAN_MAX_PRF_INTERATIONS_COUNT 255
+
 /* Function declarations and documenation */
 
 /**
@@ -87,6 +89,34 @@ int qdf_get_hmac_hash(uint8_t *type, uint8_t *key,
 		uint32_t keylen, uint8_t element_cnt,
 		uint8_t *addr[], uint32_t *addr_len, int8_t *hash);
 
+/**
+ * qdf_default_hmac_sha256_kdf()- This API calculates key data using default kdf
+ * defined in RFC4306.
+ * @secret: key which needs to be used in crypto
+ * @secret_len: key_len of secret
+ * @label: PRF label
+ * @optional_data: Data used for hash
+ * @optional_data_len: data length
+ * @key: key data output
+ * @keylen: key data length
+ *
+ * This API creates default KDF as defined in RFC4306
+ * PRF+ (K,S) = T1 | T2 | T3 | T4 | ...
+ * T1 = PRF (K, S | 0x01)
+ * T2 = PRF (K, T1 | S | 0x02)
+ * T3 = PRF (K, T2 | S | 0x03)
+ * T4 = PRF (K, T3 | S | 0x04)
+ *
+ * for every iteration its creates 32 bit of hash
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+qdf_default_hmac_sha256_kdf(uint8_t *secret, uint32_t secret_len,
+			    uint8_t *label, uint8_t *optional_data,
+			    uint32_t optional_data_len, uint8_t *key,
+			    uint32_t keylen);
+
 /**
  * qdf_get_keyed_hash: API to get hash using specific crypto and
  * scatterlist elements.

+ 57 - 0
qdf/linux/src/qdf_crypto.c

@@ -78,6 +78,63 @@ int qdf_get_hmac_hash(uint8_t *type, uint8_t *key,
 				  src_len, element_cnt,  hash);
 }
 
+QDF_STATUS
+qdf_default_hmac_sha256_kdf(uint8_t *secret, uint32_t secret_len,
+			    uint8_t *label, uint8_t *optional_data,
+			    uint32_t optional_data_len, uint8_t *key,
+			    uint32_t keylen)
+{
+	uint8_t tmp_hash[SHA256_DIGEST_SIZE] = {0};
+	uint8_t count = 1;
+	uint8_t *addr[4];
+	uint32_t len[4];
+	uint32_t current_position = 0, remaining_data = SHA256_DIGEST_SIZE;
+
+	addr[0] = tmp_hash;
+	len[0] = SHA256_DIGEST_SIZE;
+	addr[1] = label;
+	len[1] = strlen(label) + 1;
+	addr[2] = optional_data;
+	len[2] = optional_data_len;
+	addr[3] = &count;
+	len[3] = 1;
+
+	if (keylen == 0 ||
+	    (keylen > (WLAN_MAX_PRF_INTERATIONS_COUNT * SHA256_DIGEST_SIZE))) {
+		qdf_err("invalid key length %d", keylen);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	/* Create T1 */
+	if (qdf_get_hmac_hash(HMAC_SHA256_CRYPTO_TYPE, secret, secret_len, 3,
+			      &addr[1], &len[1], tmp_hash) < 0) {
+		qdf_err("failed to get hmac hash");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	/* Update hash from tmp_hash */
+	qdf_mem_copy(key + current_position, tmp_hash, remaining_data);
+	current_position += remaining_data;
+
+	for (count = 2; current_position < keylen; count++) {
+		remaining_data = keylen - current_position;
+		if (remaining_data > SHA256_DIGEST_SIZE)
+			remaining_data = SHA256_DIGEST_SIZE;
+
+		/* Create T-n */
+		if (qdf_get_hmac_hash(HMAC_SHA256_CRYPTO_TYPE, secret,
+				      secret_len, 4, addr, len, tmp_hash) < 0) {
+			qdf_err("failed to get hmac hash");
+			return QDF_STATUS_E_FAILURE;
+		}
+		/* Update hash from tmp_hash */
+		qdf_mem_copy(key + current_position, tmp_hash, remaining_data);
+		current_position += remaining_data;
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+
 /* qdf_update_dbl from RFC 5297. Length of d is AES_BLOCK_SIZE (128 bits) */
 void qdf_update_dbl(uint8_t *d)
 {

+ 20 - 0
umac/cmn_services/crypto/inc/wlan_crypto_global_api.h

@@ -981,4 +981,24 @@ void wlan_crypto_set_sae_single_pmk_bss_cap(struct wlan_objmgr_vdev *vdev,
 }
 #endif
 
+#ifdef WLAN_FEATURE_FILS_SK
+/**
+ * lim_create_fils_rik()- This API create rik using rrk coming from
+ * supplicant.
+ * @rrk: input rrk
+ * @rrk_len: rrk length
+ * @rik: Created rik
+ * @rik_len: rik length to be filled
+ *
+ * rIK = KDF (K, S), where
+ * K = rRK and
+ * S = rIK Label + "\0" + cryptosuite + length
+ * The rIK Label is the 8-bit ASCII string:
+ * Re-authentication Integrity [email protected]
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS wlan_crypto_create_fils_rik(uint8_t *rrk, uint8_t rrk_len,
+				       uint8_t *rik, uint32_t *rik_len);
+#endif /* WLAN_FEATURE_FILS_SK */
 #endif /* end of _WLAN_CRYPTO_GLOBAL_API_H_ */

+ 19 - 0
umac/cmn_services/crypto/inc/wlan_crypto_global_def.h

@@ -75,6 +75,10 @@
 #define WLAN_CRYPTO_WPI_SMS4_PADLEN  (1)
 #define WLAN_CRYPTO_WPI_SMS4_MICLEN  (16)
 
+/* FILS definitions */
+#define WLAN_CRYPTO_FILS_OPTIONAL_DATA_LEN 3
+#define WLAN_CRYPTO_FILS_RIK_LABEL "Re-authentication Integrity [email protected]"
+
 /* key used for xmit */
 #define WLAN_CRYPTO_KEY_XMIT         (0x01)
 /* key used for recv */
@@ -217,6 +221,21 @@ enum wlan_crypto_key_type {
 #define IS_WEP_CIPHER(_c)      ((_c == WLAN_CRYPTO_CIPHER_WEP) || \
 				(_c == WLAN_CRYPTO_CIPHER_WEP_40) || \
 				(_c == WLAN_CRYPTO_CIPHER_WEP_104))
+
+/*
+ * enum fils_erp_cryptosuite: this enum defines the cryptosuites used
+ * to calculate auth tag and auth tag length as defined by RFC 6696 5.3.1
+ * @HMAC_SHA256_64: sha256 with auth tag len as 64 bits
+ * @HMAC_SHA256_128: sha256 with auth tag len as 128 bits
+ * @HMAC_SHA256_256: sha256 with auth tag len as 256 bits
+ */
+enum fils_erp_cryptosuite {
+	INVALID_CRYPTO = 0, /* reserved */
+	HMAC_SHA256_64,
+	HMAC_SHA256_128,
+	HMAC_SHA256_256,
+};
+
 /**
  * struct wlan_crypto_pmksa - structure of crypto to contain pmkid
  * @bssid: bssid for which pmkid is saved

+ 34 - 1
umac/cmn_services/crypto/src/wlan_crypto_global_api.c

@@ -4486,5 +4486,38 @@ void wlan_crypto_set_sae_single_pmk_bss_cap(struct wlan_objmgr_vdev *vdev,
 	}
 }
 #endif
-
 #endif
+
+#ifdef WLAN_FEATURE_FILS_SK
+QDF_STATUS wlan_crypto_create_fils_rik(uint8_t *rrk, uint8_t rrk_len,
+				       uint8_t *rik, uint32_t *rik_len)
+{
+	uint8_t optional_data[WLAN_CRYPTO_FILS_OPTIONAL_DATA_LEN];
+	uint8_t label[] = WLAN_CRYPTO_FILS_RIK_LABEL;
+	QDF_STATUS status;
+
+	if (!rrk || !rik) {
+		crypto_err("FILS rrk/rik NULL");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	optional_data[0] = HMAC_SHA256_128;
+	/* basic validation */
+	if (rrk_len <= 0) {
+		crypto_err("invalid r_rk length %d", rrk_len);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	wlan_crypto_put_be16(&optional_data[1], rrk_len);
+	status = qdf_default_hmac_sha256_kdf(rrk, rrk_len, label, optional_data,
+					     sizeof(optional_data), rik,
+					     rrk_len);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		crypto_err("failed to create rik");
+		return status;
+	}
+	*rik_len = rrk_len;
+
+	return QDF_STATUS_SUCCESS;
+}
+#endif /* WLAN_FEATURE_FILS_SK */