int hmac_md5(v_U8_t *key, v_U8_t ksize, char *plaintext, v_U8_t psize, v_U8_t *output, v_U8_t outlen) { int ret = 0; struct crypto_ahash *tfm; struct scatterlist sg; struct ahash_request *req; struct hmac_md5_result tresult; void *hash_buff = NULL; unsigned char hash_result[64]; int i; memset(output, 0, outlen); init_completion(&tresult.completion); tfm = wcnss_wlan_crypto_alloc_ahash("hmac(md5)", CRYPTO_ALG_TYPE_AHASH, CRYPTO_ALG_TYPE_AHASH_MASK); if (IS_ERR(tfm)) { VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "crypto_alloc_ahash failed"); ret = PTR_ERR(tfm); goto err_tfm; } req = ahash_request_alloc(tfm, GFP_KERNEL); if (!req) { VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "failed to allocate request for hmac(md5)"); ret = -ENOMEM; goto err_req; } ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, hmac_md5_complete, &tresult); hash_buff = kzalloc(psize, GFP_KERNEL); if (!hash_buff) { VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "failed to kzalloc hash_buff"); ret = -ENOMEM; goto err_hash_buf; } memset(hash_result, 0, 64); memcpy(hash_buff, plaintext, psize); sg_init_one(&sg, hash_buff, psize); if (ksize) { crypto_ahash_clear_flags(tfm, ~0); ret = wcnss_wlan_crypto_ahash_setkey(tfm, key, ksize); if (ret) { VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "crypto_ahash_setkey failed"); goto err_setkey; } } ahash_request_set_crypt(req, &sg, hash_result, psize); ret = wcnss_wlan_crypto_ahash_digest(req); VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "ret 0x%x"); switch (ret) { case 0: for (i=0; i< outlen; i++) output[i] = hash_result[i]; break; case -EINPROGRESS: case -EBUSY: ret = wait_for_completion_interruptible(&tresult.completion); if (!ret && !tresult.err) { INIT_COMPLETION(tresult.completion); break; } else { VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "wait_for_completion_interruptible failed"); if (!ret) ret = tresult.err; goto out; } default: goto out; } out: err_setkey: kfree(hash_buff); err_hash_buf: ahash_request_free(req); err_req: wcnss_wlan_crypto_free_ahash(tfm); err_tfm: return ret; }
int hmac_md5(v_U8_t *key, v_U8_t ksize, char *plaintext, v_U8_t psize, v_U8_t *output, v_U8_t outlen) { int ret = 0; struct crypto_ahash *tfm; struct scatterlist sg; struct ahash_request *req; struct hmac_md5_result tresult = {.err = 0}; void *hash_buff = NULL; unsigned char hash_result[64]; int i; memset(output, 0, outlen); init_completion(&tresult.completion); #if !defined(CONFIG_CNSS) && (defined(HIF_USB) || defined(HIF_SDIO)) tfm = crypto_alloc_ahash("hmac(md5)", CRYPTO_ALG_TYPE_AHASH, CRYPTO_ALG_TYPE_AHASH_MASK); #else tfm = wcnss_wlan_crypto_alloc_ahash("hmac(md5)", CRYPTO_ALG_TYPE_AHASH, CRYPTO_ALG_TYPE_AHASH_MASK); #endif if (IS_ERR(tfm)) { VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "crypto_alloc_ahash failed"); ret = PTR_ERR(tfm); goto err_tfm; } req = ahash_request_alloc(tfm, GFP_KERNEL); if (!req) { VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "failed to allocate request for hmac(md5)"); ret = -ENOMEM; goto err_req; } ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, hmac_md5_complete, &tresult); hash_buff = kzalloc(psize, GFP_KERNEL); if (!hash_buff) { VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "failed to kzalloc hash_buff"); ret = -ENOMEM; goto err_hash_buf; } memset(hash_result, 0, 64); vos_mem_copy(hash_buff, plaintext, psize); sg_init_one(&sg, hash_buff, psize); if (ksize) { crypto_ahash_clear_flags(tfm, ~0); #if !defined(CONFIG_CNSS) && (defined(HIF_USB) || defined(HIF_SDIO)) ret = crypto_ahash_setkey(tfm, key, ksize); #else ret = wcnss_wlan_crypto_ahash_setkey(tfm, key, ksize); #endif if (ret) { VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "crypto_ahash_setkey failed"); goto err_setkey; } } ahash_request_set_crypt(req, &sg, hash_result, psize); #if !defined(CONFIG_CNSS) && (defined(HIF_USB) || defined(HIF_SDIO)) ret = crypto_ahash_digest(req); #else ret = wcnss_wlan_crypto_ahash_digest(req); #endif VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "ret 0x%x", ret); switch (ret) { case 0: for (i=0; i< outlen; i++) output[i] = hash_result[i]; break; case -EINPROGRESS: case -EBUSY: ret = wait_for_completion_interruptible(&tresult.completion); if (!ret && !tresult.err) { for (i = 0; i < outlen; i++) output[i] = hash_result[i]; INIT_COMPLETION(tresult.completion); break; } else { VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "wait_for_completion_interruptible failed"); if (!ret) ret = tresult.err; goto out; } default: goto out; } out: err_setkey: kfree(hash_buff); err_hash_buf: ahash_request_free(req); err_req: #if !defined(CONFIG_CNSS) && (defined(HIF_USB) || defined(HIF_SDIO)) crypto_free_ahash(tfm); #else wcnss_wlan_crypto_free_ahash(tfm); #endif err_tfm: return ret; } VOS_STATUS vos_md5_hmac_str(v_U32_t cryptHandle, /* Handle */ v_U8_t *pText, /* pointer to data stream */ v_U32_t textLen, /* length of data stream */ v_U8_t *pKey, /* pointer to authentication key */ v_U32_t keyLen, /* length of authentication key */ v_U8_t digest[VOS_DIGEST_MD5_SIZE])/* caller digest to be filled in */ { int ret = 0; ret = hmac_md5( pKey, //v_U8_t *key, (v_U8_t) keyLen, //v_U8_t ksize, (char *)pText, //char *plaintext, (v_U8_t) textLen, //v_U8_t psize, digest, //v_U8_t *output, VOS_DIGEST_MD5_SIZE //v_U8_t outlen ); if (ret != 0) { VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR,"hmac_md5() call failed"); return VOS_STATUS_E_FAULT; } return VOS_STATUS_SUCCESS; }