Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright 2003-2004, Instant802 Networks, Inc.
0004  * Copyright 2005-2006, Devicescape Software, Inc.
0005  * Copyright 2014-2015, Qualcomm Atheros, Inc.
0006  *
0007  * Rewrite: Copyright (C) 2013 Linaro Ltd <ard.biesheuvel@linaro.org>
0008  */
0009 
0010 #include <linux/kernel.h>
0011 #include <linux/types.h>
0012 #include <linux/err.h>
0013 #include <linux/scatterlist.h>
0014 #include <crypto/aead.h>
0015 
0016 #include "aead_api.h"
0017 
0018 int aead_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, size_t aad_len,
0019          u8 *data, size_t data_len, u8 *mic)
0020 {
0021     size_t mic_len = crypto_aead_authsize(tfm);
0022     struct scatterlist sg[3];
0023     struct aead_request *aead_req;
0024     int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm);
0025     u8 *__aad;
0026     int ret;
0027 
0028     aead_req = kzalloc(reqsize + aad_len, GFP_ATOMIC);
0029     if (!aead_req)
0030         return -ENOMEM;
0031 
0032     __aad = (u8 *)aead_req + reqsize;
0033     memcpy(__aad, aad, aad_len);
0034 
0035     sg_init_table(sg, 3);
0036     sg_set_buf(&sg[0], __aad, aad_len);
0037     sg_set_buf(&sg[1], data, data_len);
0038     sg_set_buf(&sg[2], mic, mic_len);
0039 
0040     aead_request_set_tfm(aead_req, tfm);
0041     aead_request_set_crypt(aead_req, sg, sg, data_len, b_0);
0042     aead_request_set_ad(aead_req, sg[0].length);
0043 
0044     ret = crypto_aead_encrypt(aead_req);
0045     kfree_sensitive(aead_req);
0046 
0047     return ret;
0048 }
0049 
0050 int aead_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, size_t aad_len,
0051          u8 *data, size_t data_len, u8 *mic)
0052 {
0053     size_t mic_len = crypto_aead_authsize(tfm);
0054     struct scatterlist sg[3];
0055     struct aead_request *aead_req;
0056     int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm);
0057     u8 *__aad;
0058     int err;
0059 
0060     if (data_len == 0)
0061         return -EINVAL;
0062 
0063     aead_req = kzalloc(reqsize + aad_len, GFP_ATOMIC);
0064     if (!aead_req)
0065         return -ENOMEM;
0066 
0067     __aad = (u8 *)aead_req + reqsize;
0068     memcpy(__aad, aad, aad_len);
0069 
0070     sg_init_table(sg, 3);
0071     sg_set_buf(&sg[0], __aad, aad_len);
0072     sg_set_buf(&sg[1], data, data_len);
0073     sg_set_buf(&sg[2], mic, mic_len);
0074 
0075     aead_request_set_tfm(aead_req, tfm);
0076     aead_request_set_crypt(aead_req, sg, sg, data_len + mic_len, b_0);
0077     aead_request_set_ad(aead_req, sg[0].length);
0078 
0079     err = crypto_aead_decrypt(aead_req);
0080     kfree_sensitive(aead_req);
0081 
0082     return err;
0083 }
0084 
0085 struct crypto_aead *
0086 aead_key_setup_encrypt(const char *alg, const u8 key[],
0087                size_t key_len, size_t mic_len)
0088 {
0089     struct crypto_aead *tfm;
0090     int err;
0091 
0092     tfm = crypto_alloc_aead(alg, 0, CRYPTO_ALG_ASYNC);
0093     if (IS_ERR(tfm))
0094         return tfm;
0095 
0096     err = crypto_aead_setkey(tfm, key, key_len);
0097     if (err)
0098         goto free_aead;
0099     err = crypto_aead_setauthsize(tfm, mic_len);
0100     if (err)
0101         goto free_aead;
0102 
0103     return tfm;
0104 
0105 free_aead:
0106     crypto_free_aead(tfm);
0107     return ERR_PTR(err);
0108 }
0109 
0110 void aead_key_free(struct crypto_aead *tfm)
0111 {
0112     crypto_free_aead(tfm);
0113 }