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 int qdf_get_keyed_hash(const char *alg, const uint8_t *key, 99 unsigned int key_len, const uint8_t *src[], 100 size_t *src_len, size_t num_elements, uint8_t *out) 101 { 102 struct crypto_shash *tfm; 103 int ret; 104 size_t i; 105 106 tfm = crypto_alloc_shash(alg, 0, CRYPTO_ALG_ASYNC); 107 if (IS_ERR(tfm)) { 108 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 109 FL("Failed to allocate transformation for %s: %ld"), 110 alg, PTR_ERR(tfm)); 111 return -EINVAL; 112 } 113 114 if (key && key_len) { 115 ret = crypto_shash_setkey(tfm, key, key_len); 116 if (ret) { 117 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 118 FL("Set key failed for %s, ret:%d"), 119 alg, -ret); 120 goto error; 121 } 122 } 123 124 do { 125 SHASH_DESC_ON_STACK(desc, tfm); 126 desc->tfm = tfm; 127 desc->flags = crypto_shash_get_flags(tfm); 128 129 ret = crypto_shash_init(desc); 130 if (ret) { 131 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 132 FL("Failed to init hash for %s, ret:%d"), 133 alg, -ret); 134 goto error; 135 } 136 137 for (i = 0; i < num_elements; i++) { 138 ret = crypto_shash_update(desc, src[i], src_len[i]); 139 if (ret) { 140 QDF_TRACE(QDF_MODULE_ID_QDF, 141 QDF_TRACE_LEVEL_ERROR, 142 FL("Failed to update hash for %s, ret:%d"), 143 alg, -ret); 144 goto error; 145 } 146 } 147 148 ret = crypto_shash_final(desc, out); 149 if (ret) 150 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 151 FL("Failed to get digest for %s, ret:%d"), 152 alg, -ret); 153 } while (0); 154 155 error: 156 crypto_free_shash(tfm); 157 return ret; 158 } 159 160 /* AES String to Vector from RFC 5297, 'out' should be of length AES_BLOCK_SIZE 161 */ 162 int qdf_aes_s2v(const uint8_t *key, unsigned int key_len, const uint8_t *s[], 163 size_t s_len[], size_t num_s, uint8_t *out) 164 { 165 const char *alg = "cmac(aes)"; 166 uint8_t d[AES_BLOCK_SIZE]; 167 uint8_t buf[AES_BLOCK_SIZE] = { 0 }; 168 size_t buf_len = AES_BLOCK_SIZE; 169 const uint8_t *a[1]; 170 unsigned int i; 171 uint8_t *t = NULL; 172 size_t t_len; 173 int ret; 174 175 if (num_s == 0) { 176 /* V = AES-CMAC(K, <one>) */ 177 buf[0] = 0x01; 178 a[0] = buf; 179 ret = qdf_get_keyed_hash(alg, key, key_len, a, &buf_len, 1, 180 out); 181 return ret; 182 } 183 184 /* D = AES-CMAC(K, <zero>) */ 185 a[0] = buf; 186 ret = qdf_get_keyed_hash(alg, key, key_len, a, &buf_len, 1, d); 187 if (ret) 188 goto error; 189 190 for (i = 0; i < num_s - 1; i++) { 191 /* D = qdf_update_dbl(D) xor AES-CMAC(K, Si) */ 192 qdf_update_dbl(d); 193 ret = qdf_get_keyed_hash(alg, key, key_len, &s[i], &s_len[i], 1, 194 buf); 195 if (ret) 196 goto error; 197 xor(d, buf, AES_BLOCK_SIZE); 198 } 199 200 if (s_len[i] >= AES_BLOCK_SIZE) { 201 /* len(Sn) >= 128 */ 202 /* T = Sn xorend D */ 203 t = qdf_mem_malloc(s_len[i]); 204 if (!t) 205 return -EINVAL; 206 qdf_mem_copy(t, s[i], s_len[i]); 207 xor(t + s_len[i] - AES_BLOCK_SIZE, d, AES_BLOCK_SIZE); 208 t_len = s_len[i]; 209 } else { 210 /* len(Sn) < 128 */ 211 /* T = qdf_update_dbl(D) xor pad(Sn) */ 212 qdf_update_dbl(d); 213 qdf_mem_zero(buf, AES_BLOCK_SIZE); 214 qdf_mem_copy(buf, s[i], s_len[i]); 215 buf[s_len[i]] = 0x80; 216 xor(d, s[i], AES_BLOCK_SIZE); 217 t = d; 218 t_len = AES_BLOCK_SIZE; 219 } 220 221 /* V = AES-CMAC(K, T) */ 222 a[0] = t; 223 ret = qdf_get_keyed_hash(alg, key, key_len, a, &t_len, 1, out); 224 225 error: 226 if (t && t != d) 227 qdf_mem_free(t); 228 return ret; 229 } 230 231 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0)) 232 int qdf_aes_ctr(const uint8_t *key, unsigned int key_len, uint8_t *siv, 233 const uint8_t *src, size_t src_len, uint8_t *dest, bool enc) 234 { 235 struct crypto_skcipher *tfm; 236 struct skcipher_request *req = NULL; 237 struct scatterlist sg_in, sg_out; 238 int ret; 239 240 if (!IS_VALID_CTR_KEY_LEN(key_len)) { 241 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 242 FL("Invalid key length: %u"), key_len); 243 return -EINVAL; 244 } 245 246 tfm = crypto_alloc_skcipher("ctr(aes)", 0, CRYPTO_ALG_ASYNC); 247 if (IS_ERR(tfm)) { 248 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 249 FL("Failed to alloc transformation for ctr(aes):%ld"), 250 PTR_ERR(tfm)); 251 return -EAGAIN; 252 } 253 254 req = skcipher_request_alloc(tfm, GFP_KERNEL); 255 if (!req) { 256 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 257 FL("Failed to allocate request for ctr(aes)")); 258 crypto_free_skcipher(tfm); 259 return -EAGAIN; 260 } 261 262 ret = crypto_skcipher_setkey(tfm, key, key_len); 263 if (ret) { 264 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 265 FL("Set key failed for ctr(aes), ret:%d"), -ret); 266 skcipher_request_free(req); 267 crypto_free_skcipher(tfm); 268 return ret; 269 } 270 271 sg_init_one(&sg_in, src, src_len); 272 sg_init_one(&sg_out, dest, src_len); 273 skcipher_request_set_crypt(req, &sg_in, &sg_out, src_len, siv); 274 275 if (enc) 276 ret = crypto_skcipher_encrypt(req); 277 else 278 ret = crypto_skcipher_decrypt(req); 279 280 if (ret) { 281 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 282 FL("%s failed for ctr(aes), ret:%d"), 283 enc ? "Encryption" : "Decryption", -ret); 284 } 285 286 skcipher_request_free(req); 287 crypto_free_skcipher(tfm); 288 return ret; 289 } 290 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)) 291 int qdf_aes_ctr(const uint8_t *key, unsigned int key_len, uint8_t *siv, 292 const uint8_t *src, size_t src_len, uint8_t *dest, bool enc) 293 { 294 struct crypto_ablkcipher *tfm; 295 struct ablkcipher_request *req = NULL; 296 struct scatterlist sg_in, sg_out; 297 int ret; 298 299 if (!IS_VALID_CTR_KEY_LEN(key_len)) { 300 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 301 FL("Invalid key length: %u"), key_len); 302 return -EINVAL; 303 } 304 305 tfm = crypto_alloc_ablkcipher("ctr(aes)", 0, CRYPTO_ALG_ASYNC); 306 if (IS_ERR(tfm)) { 307 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 308 FL("Failed to alloc transformation for ctr(aes):%ld"), 309 PTR_ERR(tfm)); 310 return -EAGAIN; 311 } 312 313 req = ablkcipher_request_alloc(tfm, GFP_KERNEL); 314 if (!req) { 315 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 316 FL("Failed to allocate request for ctr(aes)")); 317 crypto_free_ablkcipher(tfm); 318 return -EAGAIN; 319 } 320 321 ret = crypto_ablkcipher_setkey(tfm, key, key_len); 322 if (ret) { 323 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 324 FL("Set key failed for ctr(aes), ret:%d"), -ret); 325 ablkcipher_request_free(req); 326 crypto_free_ablkcipher(tfm); 327 return ret; 328 } 329 330 sg_init_one(&sg_in, src, src_len); 331 sg_init_one(&sg_out, dest, src_len); 332 ablkcipher_request_set_crypt(req, &sg_in, &sg_out, src_len, siv); 333 334 if (enc) 335 ret = crypto_ablkcipher_encrypt(req); 336 else 337 ret = crypto_ablkcipher_decrypt(req); 338 339 if (ret) { 340 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 341 FL("%s failed for ctr(aes), ret:%d"), 342 enc ? "Encryption" : "Decryption", -ret); 343 } 344 345 ablkcipher_request_free(req); 346 crypto_free_ablkcipher(tfm); 347 348 return ret; 349 } 350 #else 351 int qdf_aes_ctr(const uint8_t *key, unsigned int key_len, uint8_t *siv, 352 const uint8_t *src, size_t src_len, uint8_t *dest, bool enc) 353 { 354 return -EINVAL; 355 } 356 #endif 357 358 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) 359 int qdf_crypto_aes_gmac(uint8_t *key, uint16_t key_length, 360 uint8_t *iv, uint8_t *aad, uint8_t *data, 361 uint16_t data_len, uint8_t *mic) 362 { 363 struct crypto_aead *tfm; 364 int ret = 0; 365 struct scatterlist sg[4]; 366 uint16_t req_size; 367 struct aead_request *req = NULL; 368 uint8_t *aad_ptr, *input; 369 370 tfm = crypto_alloc_aead("gcm(aes)", 0, CRYPTO_ALG_ASYNC); 371 if (IS_ERR(tfm)) { 372 ret = PTR_ERR(tfm); 373 tfm = NULL; 374 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 375 "%s: crypto_alloc_aead failed (%d)", __func__, ret); 376 goto err_tfm; 377 } 378 379 ret = crypto_aead_setkey(tfm, key, key_length); 380 if (ret) { 381 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 382 "crypto_aead_setkey failed (%d)", ret); 383 goto err_tfm; 384 } 385 386 ret = crypto_aead_setauthsize(tfm, IEEE80211_MMIE_GMAC_MICLEN); 387 if (ret) { 388 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 389 "crypto_aead_setauthsize failed (%d)", ret); 390 goto err_tfm; 391 } 392 393 /* Prepare aead request */ 394 req_size = sizeof(*req) + crypto_aead_reqsize(tfm) + 395 IEEE80211_MMIE_GMAC_MICLEN + AAD_LEN; 396 req = qdf_mem_malloc(req_size); 397 if (!req) { 398 ret = -ENOMEM; 399 goto err_tfm; 400 } 401 402 input = (uint8_t *)req + sizeof(*req) + crypto_aead_reqsize(tfm); 403 aad_ptr = input + IEEE80211_MMIE_GMAC_MICLEN; 404 qdf_mem_copy(aad_ptr, aad, AAD_LEN); 405 406 /* Scatter list operations */ 407 sg_init_table(sg, 4); 408 sg_set_buf(&sg[0], aad_ptr, AAD_LEN); 409 sg_set_buf(&sg[1], data, data_len); 410 sg_set_buf(&sg[2], input, IEEE80211_MMIE_GMAC_MICLEN); 411 sg_set_buf(&sg[3], mic, IEEE80211_MMIE_GMAC_MICLEN); 412 413 aead_request_set_tfm(req, tfm); 414 aead_request_set_crypt(req, sg, sg, 0, iv); 415 aead_request_set_ad(req, 416 AAD_LEN + data_len + IEEE80211_MMIE_GMAC_MICLEN); 417 crypto_aead_encrypt(req); 418 419 err_tfm: 420 if (tfm) 421 crypto_free_aead(tfm); 422 423 if (req) 424 qdf_mem_free(req); 425 426 return ret; 427 } 428 #else 429 int qdf_crypto_aes_gmac(uint8_t *key, uint16_t key_length, 430 uint8_t *iv, uint8_t *aad, uint8_t *data, 431 uint16_t data_len, uint8_t *mic) 432 { 433 return -EINVAL; 434 } 435 #endif 436