1 /* 2 * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for 5 * any purpose with or without fee is hereby granted, provided that the 6 * above copyright notice and this permission notice appear in all 7 * copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 /** 20 * DOC: qdf_crypto.c 21 * 22 * This source file contains linux specific definitions for QDF crypto APIs 23 */ 24 25 /* Include Files */ 26 #include "qdf_crypto.h" 27 #include <linux/export.h> 28 #include <crypto/hash.h> 29 #include <crypto/aes.h> 30 #include <crypto/skcipher.h> 31 #include <crypto/aead.h> 32 #include <linux/ieee80211.h> 33 34 /* Function Definitions and Documentation */ 35 #define MAX_HMAC_ELEMENT_CNT 10 36 37 /* 38 * xor: API to calculate xor 39 * @a: first variable 40 * @b: second variable 41 * @len: length of variables 42 */ 43 static void xor(uint8_t *a, const uint8_t *b, size_t len) 44 { 45 unsigned int i; 46 47 for (i = 0; i < len; i++) 48 a[i] ^= b[i]; 49 } 50 51 int qdf_get_hash(uint8_t *type, 52 uint8_t element_cnt, uint8_t *addr[], uint32_t *addr_len, 53 int8_t *hash) 54 { 55 return qdf_get_hmac_hash(type, NULL, 0, element_cnt, 56 addr, addr_len, hash); 57 } 58 59 int qdf_get_hmac_hash(uint8_t *type, uint8_t *key, 60 uint32_t keylen, 61 uint8_t element_cnt, uint8_t *addr[], uint32_t *addr_len, 62 int8_t *hash) 63 { 64 int i; 65 size_t src_len[MAX_HMAC_ELEMENT_CNT]; 66 67 if (element_cnt > MAX_HMAC_ELEMENT_CNT) { 68 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 69 FL("Invalid element count %d"), element_cnt); 70 return -EINVAL; 71 } 72 73 for (i = 0; i < element_cnt; i++) 74 src_len[i] = addr_len[i]; 75 76 return qdf_get_keyed_hash(type, key, keylen, (const uint8_t **)addr, 77 src_len, element_cnt, hash); 78 } 79 80 /* qdf_update_dbl from RFC 5297. Length of d is AES_BLOCK_SIZE (128 bits) */ 81 void qdf_update_dbl(uint8_t *d) 82 { 83 int i; 84 uint8_t msb, msb_prev = 0; 85 86 /* left shift by 1 */ 87 for (i = AES_BLOCK_SIZE - 1; i >= 0; i--) { 88 msb = d[i] & 0x80; 89 d[i] = d[i] << 1; 90 d[i] += msb_prev ? 1 : 0; 91 msb_prev = msb; 92 } 93 94 if (msb) 95 d[AES_BLOCK_SIZE - 1] ^= 0x87; 96 } 97 98 /** 99 * set_desc_flags() - set flags variable in the shash_desc struct 100 * @desc: pointer to shash_desc struct 101 * @tfm: pointer to crypto_shash struct 102 * 103 * Set the flags variable in the shash_desc struct by getting the flag 104 * from the crypto_hash struct. The flag is not actually used, prompting 105 * its removal from kernel code in versions 5.2 and above. Thus, for 106 * versions 5.2 and above, do not set the flag variable of shash_desc. 107 */ 108 #if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0)) 109 static void set_desc_flags(struct shash_desc *desc, struct crypto_shash *tfm) 110 { 111 desc->flags = crypto_shash_get_flags(tfm); 112 } 113 #else 114 static void set_desc_flags(struct shash_desc *desc, struct crypto_shash *tfm) 115 { 116 } 117 #endif 118 119 int qdf_get_keyed_hash(const char *alg, const uint8_t *key, 120 unsigned int key_len, const uint8_t *src[], 121 size_t *src_len, size_t num_elements, uint8_t *out) 122 { 123 struct crypto_shash *tfm; 124 int ret; 125 size_t i; 126 127 tfm = crypto_alloc_shash(alg, 0, CRYPTO_ALG_ASYNC); 128 if (IS_ERR(tfm)) { 129 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 130 FL("Failed to allocate transformation for %s: %ld"), 131 alg, PTR_ERR(tfm)); 132 return -EINVAL; 133 } 134 135 if (key && key_len) { 136 ret = crypto_shash_setkey(tfm, key, key_len); 137 if (ret) { 138 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 139 FL("Set key failed for %s, ret:%d"), 140 alg, -ret); 141 goto error; 142 } 143 } 144 145 do { 146 SHASH_DESC_ON_STACK(desc, tfm); 147 desc->tfm = tfm; 148 set_desc_flags(desc, tfm); 149 150 ret = crypto_shash_init(desc); 151 if (ret) { 152 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 153 FL("Failed to init hash for %s, ret:%d"), 154 alg, -ret); 155 goto error; 156 } 157 158 for (i = 0; i < num_elements; i++) { 159 ret = crypto_shash_update(desc, src[i], src_len[i]); 160 if (ret) { 161 QDF_TRACE(QDF_MODULE_ID_QDF, 162 QDF_TRACE_LEVEL_ERROR, 163 FL("Failed to update hash for %s, ret:%d"), 164 alg, -ret); 165 goto error; 166 } 167 } 168 169 ret = crypto_shash_final(desc, out); 170 if (ret) 171 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 172 FL("Failed to get digest for %s, ret:%d"), 173 alg, -ret); 174 } while (0); 175 176 error: 177 crypto_free_shash(tfm); 178 return ret; 179 } 180 181 /* AES String to Vector from RFC 5297, 'out' should be of length AES_BLOCK_SIZE 182 */ 183 int qdf_aes_s2v(const uint8_t *key, unsigned int key_len, const uint8_t *s[], 184 size_t s_len[], size_t num_s, uint8_t *out) 185 { 186 const char *alg = "cmac(aes)"; 187 uint8_t d[AES_BLOCK_SIZE]; 188 uint8_t buf[AES_BLOCK_SIZE] = { 0 }; 189 size_t buf_len = AES_BLOCK_SIZE; 190 const uint8_t *a[1]; 191 unsigned int i; 192 uint8_t *t = NULL; 193 size_t t_len; 194 int ret; 195 196 if (num_s == 0) { 197 /* V = AES-CMAC(K, <one>) */ 198 buf[0] = 0x01; 199 a[0] = buf; 200 ret = qdf_get_keyed_hash(alg, key, key_len, a, &buf_len, 1, 201 out); 202 return ret; 203 } 204 205 /* D = AES-CMAC(K, <zero>) */ 206 a[0] = buf; 207 ret = qdf_get_keyed_hash(alg, key, key_len, a, &buf_len, 1, d); 208 if (ret) 209 goto error; 210 211 for (i = 0; i < num_s - 1; i++) { 212 /* D = qdf_update_dbl(D) xor AES-CMAC(K, Si) */ 213 qdf_update_dbl(d); 214 ret = qdf_get_keyed_hash(alg, key, key_len, &s[i], &s_len[i], 1, 215 buf); 216 if (ret) 217 goto error; 218 xor(d, buf, AES_BLOCK_SIZE); 219 } 220 221 if (s_len[i] >= AES_BLOCK_SIZE) { 222 /* len(Sn) >= 128 */ 223 /* T = Sn xorend D */ 224 t = qdf_mem_malloc(s_len[i]); 225 if (!t) 226 return -EINVAL; 227 qdf_mem_copy(t, s[i], s_len[i]); 228 xor(t + s_len[i] - AES_BLOCK_SIZE, d, AES_BLOCK_SIZE); 229 t_len = s_len[i]; 230 } else { 231 /* len(Sn) < 128 */ 232 /* T = qdf_update_dbl(D) xor pad(Sn) */ 233 qdf_update_dbl(d); 234 qdf_mem_zero(buf, AES_BLOCK_SIZE); 235 qdf_mem_copy(buf, s[i], s_len[i]); 236 buf[s_len[i]] = 0x80; 237 xor(d, s[i], AES_BLOCK_SIZE); 238 t = d; 239 t_len = AES_BLOCK_SIZE; 240 } 241 242 /* V = AES-CMAC(K, T) */ 243 a[0] = t; 244 ret = qdf_get_keyed_hash(alg, key, key_len, a, &t_len, 1, out); 245 246 error: 247 if (t && t != d) 248 qdf_mem_free(t); 249 return ret; 250 } 251 252 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0)) 253 int qdf_aes_ctr(const uint8_t *key, unsigned int key_len, uint8_t *siv, 254 const uint8_t *src, size_t src_len, uint8_t *dest, bool enc) 255 { 256 struct crypto_skcipher *tfm; 257 struct skcipher_request *req = NULL; 258 struct scatterlist sg_in, sg_out; 259 int ret; 260 261 if (!IS_VALID_CTR_KEY_LEN(key_len)) { 262 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 263 FL("Invalid key length: %u"), key_len); 264 return -EINVAL; 265 } 266 267 tfm = crypto_alloc_skcipher("ctr(aes)", 0, CRYPTO_ALG_ASYNC); 268 if (IS_ERR(tfm)) { 269 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 270 FL("Failed to alloc transformation for ctr(aes):%ld"), 271 PTR_ERR(tfm)); 272 return -EAGAIN; 273 } 274 275 req = skcipher_request_alloc(tfm, GFP_KERNEL); 276 if (!req) { 277 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 278 FL("Failed to allocate request for ctr(aes)")); 279 crypto_free_skcipher(tfm); 280 return -EAGAIN; 281 } 282 283 ret = crypto_skcipher_setkey(tfm, key, key_len); 284 if (ret) { 285 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 286 FL("Set key failed for ctr(aes), ret:%d"), -ret); 287 skcipher_request_free(req); 288 crypto_free_skcipher(tfm); 289 return ret; 290 } 291 292 sg_init_one(&sg_in, src, src_len); 293 sg_init_one(&sg_out, dest, src_len); 294 skcipher_request_set_crypt(req, &sg_in, &sg_out, src_len, siv); 295 296 if (enc) 297 ret = crypto_skcipher_encrypt(req); 298 else 299 ret = crypto_skcipher_decrypt(req); 300 301 if (ret) { 302 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 303 FL("%s failed for ctr(aes), ret:%d"), 304 enc ? "Encryption" : "Decryption", -ret); 305 } 306 307 skcipher_request_free(req); 308 crypto_free_skcipher(tfm); 309 return ret; 310 } 311 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)) 312 int qdf_aes_ctr(const uint8_t *key, unsigned int key_len, uint8_t *siv, 313 const uint8_t *src, size_t src_len, uint8_t *dest, bool enc) 314 { 315 struct crypto_ablkcipher *tfm; 316 struct ablkcipher_request *req = NULL; 317 struct scatterlist sg_in, sg_out; 318 int ret; 319 320 if (!IS_VALID_CTR_KEY_LEN(key_len)) { 321 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 322 FL("Invalid key length: %u"), key_len); 323 return -EINVAL; 324 } 325 326 tfm = crypto_alloc_ablkcipher("ctr(aes)", 0, CRYPTO_ALG_ASYNC); 327 if (IS_ERR(tfm)) { 328 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 329 FL("Failed to alloc transformation for ctr(aes):%ld"), 330 PTR_ERR(tfm)); 331 return -EAGAIN; 332 } 333 334 req = ablkcipher_request_alloc(tfm, GFP_KERNEL); 335 if (!req) { 336 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 337 FL("Failed to allocate request for ctr(aes)")); 338 crypto_free_ablkcipher(tfm); 339 return -EAGAIN; 340 } 341 342 ret = crypto_ablkcipher_setkey(tfm, key, key_len); 343 if (ret) { 344 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 345 FL("Set key failed for ctr(aes), ret:%d"), -ret); 346 ablkcipher_request_free(req); 347 crypto_free_ablkcipher(tfm); 348 return ret; 349 } 350 351 sg_init_one(&sg_in, src, src_len); 352 sg_init_one(&sg_out, dest, src_len); 353 ablkcipher_request_set_crypt(req, &sg_in, &sg_out, src_len, siv); 354 355 if (enc) 356 ret = crypto_ablkcipher_encrypt(req); 357 else 358 ret = crypto_ablkcipher_decrypt(req); 359 360 if (ret) { 361 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 362 FL("%s failed for ctr(aes), ret:%d"), 363 enc ? "Encryption" : "Decryption", -ret); 364 } 365 366 ablkcipher_request_free(req); 367 crypto_free_ablkcipher(tfm); 368 369 return ret; 370 } 371 #else 372 int qdf_aes_ctr(const uint8_t *key, unsigned int key_len, uint8_t *siv, 373 const uint8_t *src, size_t src_len, uint8_t *dest, bool enc) 374 { 375 return -EINVAL; 376 } 377 #endif 378 379 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) 380 int qdf_crypto_aes_gmac(uint8_t *key, uint16_t key_length, 381 uint8_t *iv, uint8_t *aad, uint8_t *data, 382 uint16_t data_len, uint8_t *mic) 383 { 384 struct crypto_aead *tfm; 385 int ret = 0; 386 struct scatterlist sg[4]; 387 uint16_t req_size; 388 struct aead_request *req = NULL; 389 uint8_t *aad_ptr, *input; 390 391 tfm = crypto_alloc_aead("gcm(aes)", 0, CRYPTO_ALG_ASYNC); 392 if (IS_ERR(tfm)) { 393 ret = PTR_ERR(tfm); 394 tfm = NULL; 395 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 396 "%s: crypto_alloc_aead failed (%d)", __func__, ret); 397 goto err_tfm; 398 } 399 400 ret = crypto_aead_setkey(tfm, key, key_length); 401 if (ret) { 402 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 403 "crypto_aead_setkey failed (%d)", ret); 404 goto err_tfm; 405 } 406 407 ret = crypto_aead_setauthsize(tfm, IEEE80211_MMIE_GMAC_MICLEN); 408 if (ret) { 409 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 410 "crypto_aead_setauthsize failed (%d)", ret); 411 goto err_tfm; 412 } 413 414 /* Prepare aead request */ 415 req_size = sizeof(*req) + crypto_aead_reqsize(tfm) + 416 IEEE80211_MMIE_GMAC_MICLEN + AAD_LEN; 417 req = qdf_mem_malloc(req_size); 418 if (!req) { 419 ret = -ENOMEM; 420 goto err_tfm; 421 } 422 423 input = (uint8_t *)req + sizeof(*req) + crypto_aead_reqsize(tfm); 424 aad_ptr = input + IEEE80211_MMIE_GMAC_MICLEN; 425 qdf_mem_copy(aad_ptr, aad, AAD_LEN); 426 427 /* Scatter list operations */ 428 sg_init_table(sg, 4); 429 sg_set_buf(&sg[0], aad_ptr, AAD_LEN); 430 sg_set_buf(&sg[1], data, data_len); 431 sg_set_buf(&sg[2], input, IEEE80211_MMIE_GMAC_MICLEN); 432 sg_set_buf(&sg[3], mic, IEEE80211_MMIE_GMAC_MICLEN); 433 434 aead_request_set_tfm(req, tfm); 435 aead_request_set_crypt(req, sg, sg, 0, iv); 436 aead_request_set_ad(req, 437 AAD_LEN + data_len + IEEE80211_MMIE_GMAC_MICLEN); 438 crypto_aead_encrypt(req); 439 440 err_tfm: 441 if (tfm) 442 crypto_free_aead(tfm); 443 444 if (req) 445 qdf_mem_free(req); 446 447 return ret; 448 } 449 #else 450 int qdf_crypto_aes_gmac(uint8_t *key, uint16_t key_length, 451 uint8_t *iv, uint8_t *aad, uint8_t *data, 452 uint16_t data_len, uint8_t *mic) 453 { 454 return -EINVAL; 455 } 456 #endif 457