14a49b499SJoy Latten /* 24a49b499SJoy Latten * CCM: Counter with CBC-MAC 34a49b499SJoy Latten * 44a49b499SJoy Latten * (C) Copyright IBM Corp. 2007 - Joy Latten <latten@us.ibm.com> 54a49b499SJoy Latten * 64a49b499SJoy Latten * This program is free software; you can redistribute it and/or modify it 74a49b499SJoy Latten * under the terms of the GNU General Public License as published by the Free 84a49b499SJoy Latten * Software Foundation; either version 2 of the License, or (at your option) 94a49b499SJoy Latten * any later version. 104a49b499SJoy Latten * 114a49b499SJoy Latten */ 124a49b499SJoy Latten 134a49b499SJoy Latten #include <crypto/internal/aead.h> 144a49b499SJoy Latten #include <crypto/internal/skcipher.h> 154a49b499SJoy Latten #include <crypto/scatterwalk.h> 164a49b499SJoy Latten #include <linux/err.h> 174a49b499SJoy Latten #include <linux/init.h> 184a49b499SJoy Latten #include <linux/kernel.h> 194a49b499SJoy Latten #include <linux/module.h> 204a49b499SJoy Latten #include <linux/slab.h> 214a49b499SJoy Latten 224a49b499SJoy Latten #include "internal.h" 234a49b499SJoy Latten 244a49b499SJoy Latten struct ccm_instance_ctx { 254a49b499SJoy Latten struct crypto_skcipher_spawn ctr; 264a49b499SJoy Latten struct crypto_spawn cipher; 274a49b499SJoy Latten }; 284a49b499SJoy Latten 294a49b499SJoy Latten struct crypto_ccm_ctx { 304a49b499SJoy Latten struct crypto_cipher *cipher; 31464b93a3SHerbert Xu struct crypto_skcipher *ctr; 324a49b499SJoy Latten }; 334a49b499SJoy Latten 344a49b499SJoy Latten struct crypto_rfc4309_ctx { 354a49b499SJoy Latten struct crypto_aead *child; 364a49b499SJoy Latten u8 nonce[3]; 374a49b499SJoy Latten }; 384a49b499SJoy Latten 3981c4c35eSHerbert Xu struct crypto_rfc4309_req_ctx { 4081c4c35eSHerbert Xu struct scatterlist src[3]; 4181c4c35eSHerbert Xu struct scatterlist dst[3]; 4281c4c35eSHerbert Xu struct aead_request subreq; 4381c4c35eSHerbert Xu }; 4481c4c35eSHerbert Xu 454a49b499SJoy Latten struct crypto_ccm_req_priv_ctx { 464a49b499SJoy Latten u8 odata[16]; 474a49b499SJoy Latten u8 idata[16]; 484a49b499SJoy Latten u8 auth_tag[16]; 494a49b499SJoy Latten u32 ilen; 504a49b499SJoy Latten u32 flags; 5181c4c35eSHerbert Xu struct scatterlist src[3]; 5281c4c35eSHerbert Xu struct scatterlist dst[3]; 53464b93a3SHerbert Xu struct skcipher_request skreq; 544a49b499SJoy Latten }; 554a49b499SJoy Latten 564a49b499SJoy Latten static inline struct crypto_ccm_req_priv_ctx *crypto_ccm_reqctx( 574a49b499SJoy Latten struct aead_request *req) 584a49b499SJoy Latten { 594a49b499SJoy Latten unsigned long align = crypto_aead_alignmask(crypto_aead_reqtfm(req)); 604a49b499SJoy Latten 614a49b499SJoy Latten return (void *)PTR_ALIGN((u8 *)aead_request_ctx(req), align + 1); 624a49b499SJoy Latten } 634a49b499SJoy Latten 644a49b499SJoy Latten static int set_msg_len(u8 *block, unsigned int msglen, int csize) 654a49b499SJoy Latten { 664a49b499SJoy Latten __be32 data; 674a49b499SJoy Latten 684a49b499SJoy Latten memset(block, 0, csize); 694a49b499SJoy Latten block += csize; 704a49b499SJoy Latten 714a49b499SJoy Latten if (csize >= 4) 724a49b499SJoy Latten csize = 4; 734a49b499SJoy Latten else if (msglen > (1 << (8 * csize))) 744a49b499SJoy Latten return -EOVERFLOW; 754a49b499SJoy Latten 764a49b499SJoy Latten data = cpu_to_be32(msglen); 774a49b499SJoy Latten memcpy(block - csize, (u8 *)&data + 4 - csize, csize); 784a49b499SJoy Latten 794a49b499SJoy Latten return 0; 804a49b499SJoy Latten } 814a49b499SJoy Latten 824a49b499SJoy Latten static int crypto_ccm_setkey(struct crypto_aead *aead, const u8 *key, 834a49b499SJoy Latten unsigned int keylen) 844a49b499SJoy Latten { 854a49b499SJoy Latten struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead); 86464b93a3SHerbert Xu struct crypto_skcipher *ctr = ctx->ctr; 874a49b499SJoy Latten struct crypto_cipher *tfm = ctx->cipher; 884a49b499SJoy Latten int err = 0; 894a49b499SJoy Latten 90464b93a3SHerbert Xu crypto_skcipher_clear_flags(ctr, CRYPTO_TFM_REQ_MASK); 91464b93a3SHerbert Xu crypto_skcipher_set_flags(ctr, crypto_aead_get_flags(aead) & 924a49b499SJoy Latten CRYPTO_TFM_REQ_MASK); 93464b93a3SHerbert Xu err = crypto_skcipher_setkey(ctr, key, keylen); 94464b93a3SHerbert Xu crypto_aead_set_flags(aead, crypto_skcipher_get_flags(ctr) & 954a49b499SJoy Latten CRYPTO_TFM_RES_MASK); 964a49b499SJoy Latten if (err) 974a49b499SJoy Latten goto out; 984a49b499SJoy Latten 994a49b499SJoy Latten crypto_cipher_clear_flags(tfm, CRYPTO_TFM_REQ_MASK); 1004a49b499SJoy Latten crypto_cipher_set_flags(tfm, crypto_aead_get_flags(aead) & 1014a49b499SJoy Latten CRYPTO_TFM_REQ_MASK); 1024a49b499SJoy Latten err = crypto_cipher_setkey(tfm, key, keylen); 1034a49b499SJoy Latten crypto_aead_set_flags(aead, crypto_cipher_get_flags(tfm) & 1044a49b499SJoy Latten CRYPTO_TFM_RES_MASK); 1054a49b499SJoy Latten 1064a49b499SJoy Latten out: 1074a49b499SJoy Latten return err; 1084a49b499SJoy Latten } 1094a49b499SJoy Latten 1104a49b499SJoy Latten static int crypto_ccm_setauthsize(struct crypto_aead *tfm, 1114a49b499SJoy Latten unsigned int authsize) 1124a49b499SJoy Latten { 1134a49b499SJoy Latten switch (authsize) { 1144a49b499SJoy Latten case 4: 1154a49b499SJoy Latten case 6: 1164a49b499SJoy Latten case 8: 1174a49b499SJoy Latten case 10: 1184a49b499SJoy Latten case 12: 1194a49b499SJoy Latten case 14: 1204a49b499SJoy Latten case 16: 1214a49b499SJoy Latten break; 1224a49b499SJoy Latten default: 1234a49b499SJoy Latten return -EINVAL; 1244a49b499SJoy Latten } 1254a49b499SJoy Latten 1264a49b499SJoy Latten return 0; 1274a49b499SJoy Latten } 1284a49b499SJoy Latten 1294a49b499SJoy Latten static int format_input(u8 *info, struct aead_request *req, 1304a49b499SJoy Latten unsigned int cryptlen) 1314a49b499SJoy Latten { 1324a49b499SJoy Latten struct crypto_aead *aead = crypto_aead_reqtfm(req); 1334a49b499SJoy Latten unsigned int lp = req->iv[0]; 1344a49b499SJoy Latten unsigned int l = lp + 1; 1354a49b499SJoy Latten unsigned int m; 1364a49b499SJoy Latten 1374a49b499SJoy Latten m = crypto_aead_authsize(aead); 1384a49b499SJoy Latten 1394a49b499SJoy Latten memcpy(info, req->iv, 16); 1404a49b499SJoy Latten 1414a49b499SJoy Latten /* format control info per RFC 3610 and 1424a49b499SJoy Latten * NIST Special Publication 800-38C 1434a49b499SJoy Latten */ 1444a49b499SJoy Latten *info |= (8 * ((m - 2) / 2)); 1454a49b499SJoy Latten if (req->assoclen) 1464a49b499SJoy Latten *info |= 64; 1474a49b499SJoy Latten 1484a49b499SJoy Latten return set_msg_len(info + 16 - l, cryptlen, l); 1494a49b499SJoy Latten } 1504a49b499SJoy Latten 1514a49b499SJoy Latten static int format_adata(u8 *adata, unsigned int a) 1524a49b499SJoy Latten { 1534a49b499SJoy Latten int len = 0; 1544a49b499SJoy Latten 1554a49b499SJoy Latten /* add control info for associated data 1564a49b499SJoy Latten * RFC 3610 and NIST Special Publication 800-38C 1574a49b499SJoy Latten */ 1584a49b499SJoy Latten if (a < 65280) { 1594a49b499SJoy Latten *(__be16 *)adata = cpu_to_be16(a); 1604a49b499SJoy Latten len = 2; 1614a49b499SJoy Latten } else { 1624a49b499SJoy Latten *(__be16 *)adata = cpu_to_be16(0xfffe); 1634a49b499SJoy Latten *(__be32 *)&adata[2] = cpu_to_be32(a); 1644a49b499SJoy Latten len = 6; 1654a49b499SJoy Latten } 1664a49b499SJoy Latten 1674a49b499SJoy Latten return len; 1684a49b499SJoy Latten } 1694a49b499SJoy Latten 1704a49b499SJoy Latten static void compute_mac(struct crypto_cipher *tfm, u8 *data, int n, 1714a49b499SJoy Latten struct crypto_ccm_req_priv_ctx *pctx) 1724a49b499SJoy Latten { 1734a49b499SJoy Latten unsigned int bs = 16; 1744a49b499SJoy Latten u8 *odata = pctx->odata; 1754a49b499SJoy Latten u8 *idata = pctx->idata; 1764a49b499SJoy Latten int datalen, getlen; 1774a49b499SJoy Latten 1784a49b499SJoy Latten datalen = n; 1794a49b499SJoy Latten 1804a49b499SJoy Latten /* first time in here, block may be partially filled. */ 1814a49b499SJoy Latten getlen = bs - pctx->ilen; 1824a49b499SJoy Latten if (datalen >= getlen) { 1834a49b499SJoy Latten memcpy(idata + pctx->ilen, data, getlen); 1844a49b499SJoy Latten crypto_xor(odata, idata, bs); 1854a49b499SJoy Latten crypto_cipher_encrypt_one(tfm, odata, odata); 1864a49b499SJoy Latten datalen -= getlen; 1874a49b499SJoy Latten data += getlen; 1884a49b499SJoy Latten pctx->ilen = 0; 1894a49b499SJoy Latten } 1904a49b499SJoy Latten 1914a49b499SJoy Latten /* now encrypt rest of data */ 1924a49b499SJoy Latten while (datalen >= bs) { 1934a49b499SJoy Latten crypto_xor(odata, data, bs); 1944a49b499SJoy Latten crypto_cipher_encrypt_one(tfm, odata, odata); 1954a49b499SJoy Latten 1964a49b499SJoy Latten datalen -= bs; 1974a49b499SJoy Latten data += bs; 1984a49b499SJoy Latten } 1994a49b499SJoy Latten 2004a49b499SJoy Latten /* check and see if there's leftover data that wasn't 2014a49b499SJoy Latten * enough to fill a block. 2024a49b499SJoy Latten */ 2034a49b499SJoy Latten if (datalen) { 2044a49b499SJoy Latten memcpy(idata + pctx->ilen, data, datalen); 2054a49b499SJoy Latten pctx->ilen += datalen; 2064a49b499SJoy Latten } 2074a49b499SJoy Latten } 2084a49b499SJoy Latten 2094a49b499SJoy Latten static void get_data_to_compute(struct crypto_cipher *tfm, 2104a49b499SJoy Latten struct crypto_ccm_req_priv_ctx *pctx, 2114a49b499SJoy Latten struct scatterlist *sg, unsigned int len) 2124a49b499SJoy Latten { 2134a49b499SJoy Latten struct scatter_walk walk; 2144a49b499SJoy Latten u8 *data_src; 2154a49b499SJoy Latten int n; 2164a49b499SJoy Latten 2174a49b499SJoy Latten scatterwalk_start(&walk, sg); 2184a49b499SJoy Latten 2194a49b499SJoy Latten while (len) { 2204a49b499SJoy Latten n = scatterwalk_clamp(&walk, len); 2214a49b499SJoy Latten if (!n) { 2224a49b499SJoy Latten scatterwalk_start(&walk, sg_next(walk.sg)); 2234a49b499SJoy Latten n = scatterwalk_clamp(&walk, len); 2244a49b499SJoy Latten } 225f0dfc0b0SCong Wang data_src = scatterwalk_map(&walk); 2264a49b499SJoy Latten 2274a49b499SJoy Latten compute_mac(tfm, data_src, n, pctx); 2284a49b499SJoy Latten len -= n; 2294a49b499SJoy Latten 230f0dfc0b0SCong Wang scatterwalk_unmap(data_src); 2314a49b499SJoy Latten scatterwalk_advance(&walk, n); 2324a49b499SJoy Latten scatterwalk_done(&walk, 0, len); 2334a49b499SJoy Latten if (len) 2344a49b499SJoy Latten crypto_yield(pctx->flags); 2354a49b499SJoy Latten } 2364a49b499SJoy Latten 2374a49b499SJoy Latten /* any leftover needs padding and then encrypted */ 2384a49b499SJoy Latten if (pctx->ilen) { 2394a49b499SJoy Latten int padlen; 2404a49b499SJoy Latten u8 *odata = pctx->odata; 2414a49b499SJoy Latten u8 *idata = pctx->idata; 2424a49b499SJoy Latten 2434a49b499SJoy Latten padlen = 16 - pctx->ilen; 2444a49b499SJoy Latten memset(idata + pctx->ilen, 0, padlen); 2454a49b499SJoy Latten crypto_xor(odata, idata, 16); 2464a49b499SJoy Latten crypto_cipher_encrypt_one(tfm, odata, odata); 2474a49b499SJoy Latten pctx->ilen = 0; 2484a49b499SJoy Latten } 2494a49b499SJoy Latten } 2504a49b499SJoy Latten 2514a49b499SJoy Latten static int crypto_ccm_auth(struct aead_request *req, struct scatterlist *plain, 2524a49b499SJoy Latten unsigned int cryptlen) 2534a49b499SJoy Latten { 2544a49b499SJoy Latten struct crypto_aead *aead = crypto_aead_reqtfm(req); 2554a49b499SJoy Latten struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead); 2564a49b499SJoy Latten struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req); 2574a49b499SJoy Latten struct crypto_cipher *cipher = ctx->cipher; 2584a49b499SJoy Latten unsigned int assoclen = req->assoclen; 2594a49b499SJoy Latten u8 *odata = pctx->odata; 2604a49b499SJoy Latten u8 *idata = pctx->idata; 2614a49b499SJoy Latten int err; 2624a49b499SJoy Latten 2634a49b499SJoy Latten /* format control data for input */ 2644a49b499SJoy Latten err = format_input(odata, req, cryptlen); 2654a49b499SJoy Latten if (err) 2664a49b499SJoy Latten goto out; 2674a49b499SJoy Latten 2684a49b499SJoy Latten /* encrypt first block to use as start in computing mac */ 2694a49b499SJoy Latten crypto_cipher_encrypt_one(cipher, odata, odata); 2704a49b499SJoy Latten 2714a49b499SJoy Latten /* format associated data and compute into mac */ 2724a49b499SJoy Latten if (assoclen) { 2734a49b499SJoy Latten pctx->ilen = format_adata(idata, assoclen); 27481c4c35eSHerbert Xu get_data_to_compute(cipher, pctx, req->src, req->assoclen); 275516280e7SJarod Wilson } else { 276516280e7SJarod Wilson pctx->ilen = 0; 2774a49b499SJoy Latten } 2784a49b499SJoy Latten 2794a49b499SJoy Latten /* compute plaintext into mac */ 2805638cabfSHoria Geanta if (cryptlen) 2814a49b499SJoy Latten get_data_to_compute(cipher, pctx, plain, cryptlen); 2824a49b499SJoy Latten 2834a49b499SJoy Latten out: 2844a49b499SJoy Latten return err; 2854a49b499SJoy Latten } 2864a49b499SJoy Latten 2874a49b499SJoy Latten static void crypto_ccm_encrypt_done(struct crypto_async_request *areq, int err) 2884a49b499SJoy Latten { 2894a49b499SJoy Latten struct aead_request *req = areq->data; 2904a49b499SJoy Latten struct crypto_aead *aead = crypto_aead_reqtfm(req); 2914a49b499SJoy Latten struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req); 2924a49b499SJoy Latten u8 *odata = pctx->odata; 2934a49b499SJoy Latten 2944a49b499SJoy Latten if (!err) 29581c4c35eSHerbert Xu scatterwalk_map_and_copy(odata, req->dst, 29681c4c35eSHerbert Xu req->assoclen + req->cryptlen, 2974a49b499SJoy Latten crypto_aead_authsize(aead), 1); 2984a49b499SJoy Latten aead_request_complete(req, err); 2994a49b499SJoy Latten } 3004a49b499SJoy Latten 3014a49b499SJoy Latten static inline int crypto_ccm_check_iv(const u8 *iv) 3024a49b499SJoy Latten { 3034a49b499SJoy Latten /* 2 <= L <= 8, so 1 <= L' <= 7. */ 3044a49b499SJoy Latten if (1 > iv[0] || iv[0] > 7) 3054a49b499SJoy Latten return -EINVAL; 3064a49b499SJoy Latten 3074a49b499SJoy Latten return 0; 3084a49b499SJoy Latten } 3094a49b499SJoy Latten 31081c4c35eSHerbert Xu static int crypto_ccm_init_crypt(struct aead_request *req, u8 *tag) 31181c4c35eSHerbert Xu { 31281c4c35eSHerbert Xu struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req); 31381c4c35eSHerbert Xu struct scatterlist *sg; 31481c4c35eSHerbert Xu u8 *iv = req->iv; 31581c4c35eSHerbert Xu int err; 31681c4c35eSHerbert Xu 31781c4c35eSHerbert Xu err = crypto_ccm_check_iv(iv); 31881c4c35eSHerbert Xu if (err) 31981c4c35eSHerbert Xu return err; 32081c4c35eSHerbert Xu 32181c4c35eSHerbert Xu pctx->flags = aead_request_flags(req); 32281c4c35eSHerbert Xu 32381c4c35eSHerbert Xu /* Note: rfc 3610 and NIST 800-38C require counter of 32481c4c35eSHerbert Xu * zero to encrypt auth tag. 32581c4c35eSHerbert Xu */ 32681c4c35eSHerbert Xu memset(iv + 15 - iv[0], 0, iv[0] + 1); 32781c4c35eSHerbert Xu 32881c4c35eSHerbert Xu sg_init_table(pctx->src, 3); 32981c4c35eSHerbert Xu sg_set_buf(pctx->src, tag, 16); 33081c4c35eSHerbert Xu sg = scatterwalk_ffwd(pctx->src + 1, req->src, req->assoclen); 33181c4c35eSHerbert Xu if (sg != pctx->src + 1) 33281c4c35eSHerbert Xu sg_chain(pctx->src, 2, sg); 33381c4c35eSHerbert Xu 33481c4c35eSHerbert Xu if (req->src != req->dst) { 33581c4c35eSHerbert Xu sg_init_table(pctx->dst, 3); 33681c4c35eSHerbert Xu sg_set_buf(pctx->dst, tag, 16); 33781c4c35eSHerbert Xu sg = scatterwalk_ffwd(pctx->dst + 1, req->dst, req->assoclen); 33881c4c35eSHerbert Xu if (sg != pctx->dst + 1) 33981c4c35eSHerbert Xu sg_chain(pctx->dst, 2, sg); 34081c4c35eSHerbert Xu } 34181c4c35eSHerbert Xu 34281c4c35eSHerbert Xu return 0; 34381c4c35eSHerbert Xu } 34481c4c35eSHerbert Xu 3454a49b499SJoy Latten static int crypto_ccm_encrypt(struct aead_request *req) 3464a49b499SJoy Latten { 3474a49b499SJoy Latten struct crypto_aead *aead = crypto_aead_reqtfm(req); 3484a49b499SJoy Latten struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead); 3494a49b499SJoy Latten struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req); 350464b93a3SHerbert Xu struct skcipher_request *skreq = &pctx->skreq; 3514a49b499SJoy Latten struct scatterlist *dst; 3524a49b499SJoy Latten unsigned int cryptlen = req->cryptlen; 3534a49b499SJoy Latten u8 *odata = pctx->odata; 3544a49b499SJoy Latten u8 *iv = req->iv; 3554a49b499SJoy Latten int err; 3564a49b499SJoy Latten 35781c4c35eSHerbert Xu err = crypto_ccm_init_crypt(req, odata); 3584a49b499SJoy Latten if (err) 3594a49b499SJoy Latten return err; 3604a49b499SJoy Latten 36181c4c35eSHerbert Xu err = crypto_ccm_auth(req, sg_next(pctx->src), cryptlen); 3624a49b499SJoy Latten if (err) 3634a49b499SJoy Latten return err; 3644a49b499SJoy Latten 3654a49b499SJoy Latten dst = pctx->src; 36681c4c35eSHerbert Xu if (req->src != req->dst) 3674a49b499SJoy Latten dst = pctx->dst; 3684a49b499SJoy Latten 369464b93a3SHerbert Xu skcipher_request_set_tfm(skreq, ctx->ctr); 370464b93a3SHerbert Xu skcipher_request_set_callback(skreq, pctx->flags, 3714a49b499SJoy Latten crypto_ccm_encrypt_done, req); 372464b93a3SHerbert Xu skcipher_request_set_crypt(skreq, pctx->src, dst, cryptlen + 16, iv); 373464b93a3SHerbert Xu err = crypto_skcipher_encrypt(skreq); 3744a49b499SJoy Latten if (err) 3754a49b499SJoy Latten return err; 3764a49b499SJoy Latten 3774a49b499SJoy Latten /* copy authtag to end of dst */ 37881c4c35eSHerbert Xu scatterwalk_map_and_copy(odata, sg_next(dst), cryptlen, 3794a49b499SJoy Latten crypto_aead_authsize(aead), 1); 3804a49b499SJoy Latten return err; 3814a49b499SJoy Latten } 3824a49b499SJoy Latten 3834a49b499SJoy Latten static void crypto_ccm_decrypt_done(struct crypto_async_request *areq, 3844a49b499SJoy Latten int err) 3854a49b499SJoy Latten { 3864a49b499SJoy Latten struct aead_request *req = areq->data; 3874a49b499SJoy Latten struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req); 3884a49b499SJoy Latten struct crypto_aead *aead = crypto_aead_reqtfm(req); 3894a49b499SJoy Latten unsigned int authsize = crypto_aead_authsize(aead); 3904a49b499SJoy Latten unsigned int cryptlen = req->cryptlen - authsize; 39181c4c35eSHerbert Xu struct scatterlist *dst; 39281c4c35eSHerbert Xu 39381c4c35eSHerbert Xu pctx->flags = 0; 39481c4c35eSHerbert Xu 39581c4c35eSHerbert Xu dst = sg_next(req->src == req->dst ? pctx->src : pctx->dst); 3964a49b499SJoy Latten 3974a49b499SJoy Latten if (!err) { 39881c4c35eSHerbert Xu err = crypto_ccm_auth(req, dst, cryptlen); 3996bf37e5aSJames Yonan if (!err && crypto_memneq(pctx->auth_tag, pctx->odata, authsize)) 4004a49b499SJoy Latten err = -EBADMSG; 4014a49b499SJoy Latten } 4024a49b499SJoy Latten aead_request_complete(req, err); 4034a49b499SJoy Latten } 4044a49b499SJoy Latten 4054a49b499SJoy Latten static int crypto_ccm_decrypt(struct aead_request *req) 4064a49b499SJoy Latten { 4074a49b499SJoy Latten struct crypto_aead *aead = crypto_aead_reqtfm(req); 4084a49b499SJoy Latten struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead); 4094a49b499SJoy Latten struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req); 410464b93a3SHerbert Xu struct skcipher_request *skreq = &pctx->skreq; 4114a49b499SJoy Latten struct scatterlist *dst; 4124a49b499SJoy Latten unsigned int authsize = crypto_aead_authsize(aead); 4134a49b499SJoy Latten unsigned int cryptlen = req->cryptlen; 4144a49b499SJoy Latten u8 *authtag = pctx->auth_tag; 4154a49b499SJoy Latten u8 *odata = pctx->odata; 4164a49b499SJoy Latten u8 *iv = req->iv; 4174a49b499SJoy Latten int err; 4184a49b499SJoy Latten 4194a49b499SJoy Latten cryptlen -= authsize; 4204a49b499SJoy Latten 42181c4c35eSHerbert Xu err = crypto_ccm_init_crypt(req, authtag); 4224a49b499SJoy Latten if (err) 4234a49b499SJoy Latten return err; 4244a49b499SJoy Latten 42581c4c35eSHerbert Xu scatterwalk_map_and_copy(authtag, sg_next(pctx->src), cryptlen, 42681c4c35eSHerbert Xu authsize, 0); 4274a49b499SJoy Latten 4284a49b499SJoy Latten dst = pctx->src; 42981c4c35eSHerbert Xu if (req->src != req->dst) 4304a49b499SJoy Latten dst = pctx->dst; 4314a49b499SJoy Latten 432464b93a3SHerbert Xu skcipher_request_set_tfm(skreq, ctx->ctr); 433464b93a3SHerbert Xu skcipher_request_set_callback(skreq, pctx->flags, 4344a49b499SJoy Latten crypto_ccm_decrypt_done, req); 435464b93a3SHerbert Xu skcipher_request_set_crypt(skreq, pctx->src, dst, cryptlen + 16, iv); 436464b93a3SHerbert Xu err = crypto_skcipher_decrypt(skreq); 4374a49b499SJoy Latten if (err) 4384a49b499SJoy Latten return err; 4394a49b499SJoy Latten 44081c4c35eSHerbert Xu err = crypto_ccm_auth(req, sg_next(dst), cryptlen); 4414a49b499SJoy Latten if (err) 4424a49b499SJoy Latten return err; 4434a49b499SJoy Latten 4444a49b499SJoy Latten /* verify */ 4456bf37e5aSJames Yonan if (crypto_memneq(authtag, odata, authsize)) 4464a49b499SJoy Latten return -EBADMSG; 4474a49b499SJoy Latten 4484a49b499SJoy Latten return err; 4494a49b499SJoy Latten } 4504a49b499SJoy Latten 45181c4c35eSHerbert Xu static int crypto_ccm_init_tfm(struct crypto_aead *tfm) 4524a49b499SJoy Latten { 45381c4c35eSHerbert Xu struct aead_instance *inst = aead_alg_instance(tfm); 45481c4c35eSHerbert Xu struct ccm_instance_ctx *ictx = aead_instance_ctx(inst); 45581c4c35eSHerbert Xu struct crypto_ccm_ctx *ctx = crypto_aead_ctx(tfm); 4564a49b499SJoy Latten struct crypto_cipher *cipher; 457464b93a3SHerbert Xu struct crypto_skcipher *ctr; 4584a49b499SJoy Latten unsigned long align; 4594a49b499SJoy Latten int err; 4604a49b499SJoy Latten 4614a49b499SJoy Latten cipher = crypto_spawn_cipher(&ictx->cipher); 4624a49b499SJoy Latten if (IS_ERR(cipher)) 4634a49b499SJoy Latten return PTR_ERR(cipher); 4644a49b499SJoy Latten 465464b93a3SHerbert Xu ctr = crypto_spawn_skcipher2(&ictx->ctr); 4664a49b499SJoy Latten err = PTR_ERR(ctr); 4674a49b499SJoy Latten if (IS_ERR(ctr)) 4684a49b499SJoy Latten goto err_free_cipher; 4694a49b499SJoy Latten 4704a49b499SJoy Latten ctx->cipher = cipher; 4714a49b499SJoy Latten ctx->ctr = ctr; 4724a49b499SJoy Latten 47381c4c35eSHerbert Xu align = crypto_aead_alignmask(tfm); 4744a49b499SJoy Latten align &= ~(crypto_tfm_ctx_alignment() - 1); 47581c4c35eSHerbert Xu crypto_aead_set_reqsize( 47681c4c35eSHerbert Xu tfm, 4772c221ad3SHerbert Xu align + sizeof(struct crypto_ccm_req_priv_ctx) + 478464b93a3SHerbert Xu crypto_skcipher_reqsize(ctr)); 4794a49b499SJoy Latten 4804a49b499SJoy Latten return 0; 4814a49b499SJoy Latten 4824a49b499SJoy Latten err_free_cipher: 4834a49b499SJoy Latten crypto_free_cipher(cipher); 4844a49b499SJoy Latten return err; 4854a49b499SJoy Latten } 4864a49b499SJoy Latten 48781c4c35eSHerbert Xu static void crypto_ccm_exit_tfm(struct crypto_aead *tfm) 4884a49b499SJoy Latten { 48981c4c35eSHerbert Xu struct crypto_ccm_ctx *ctx = crypto_aead_ctx(tfm); 4904a49b499SJoy Latten 4914a49b499SJoy Latten crypto_free_cipher(ctx->cipher); 492464b93a3SHerbert Xu crypto_free_skcipher(ctx->ctr); 4934a49b499SJoy Latten } 4944a49b499SJoy Latten 49581c4c35eSHerbert Xu static void crypto_ccm_free(struct aead_instance *inst) 49681c4c35eSHerbert Xu { 49781c4c35eSHerbert Xu struct ccm_instance_ctx *ctx = aead_instance_ctx(inst); 49881c4c35eSHerbert Xu 49981c4c35eSHerbert Xu crypto_drop_spawn(&ctx->cipher); 50081c4c35eSHerbert Xu crypto_drop_skcipher(&ctx->ctr); 50181c4c35eSHerbert Xu kfree(inst); 50281c4c35eSHerbert Xu } 50381c4c35eSHerbert Xu 50481c4c35eSHerbert Xu static int crypto_ccm_create_common(struct crypto_template *tmpl, 50581c4c35eSHerbert Xu struct rtattr **tb, 5064a49b499SJoy Latten const char *full_name, 5074a49b499SJoy Latten const char *ctr_name, 5084a49b499SJoy Latten const char *cipher_name) 5094a49b499SJoy Latten { 5104a49b499SJoy Latten struct crypto_attr_type *algt; 51181c4c35eSHerbert Xu struct aead_instance *inst; 512464b93a3SHerbert Xu struct skcipher_alg *ctr; 5134a49b499SJoy Latten struct crypto_alg *cipher; 5144a49b499SJoy Latten struct ccm_instance_ctx *ictx; 5154a49b499SJoy Latten int err; 5164a49b499SJoy Latten 5174a49b499SJoy Latten algt = crypto_get_attr_type(tb); 5184a49b499SJoy Latten if (IS_ERR(algt)) 51981c4c35eSHerbert Xu return PTR_ERR(algt); 5204a49b499SJoy Latten 5215e4b8c1fSHerbert Xu if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask) 52281c4c35eSHerbert Xu return -EINVAL; 5234a49b499SJoy Latten 5244a49b499SJoy Latten cipher = crypto_alg_mod_lookup(cipher_name, CRYPTO_ALG_TYPE_CIPHER, 5254a49b499SJoy Latten CRYPTO_ALG_TYPE_MASK); 5264a49b499SJoy Latten if (IS_ERR(cipher)) 52781c4c35eSHerbert Xu return PTR_ERR(cipher); 5284a49b499SJoy Latten 5294a49b499SJoy Latten err = -EINVAL; 5304a49b499SJoy Latten if (cipher->cra_blocksize != 16) 5314a49b499SJoy Latten goto out_put_cipher; 5324a49b499SJoy Latten 5334a49b499SJoy Latten inst = kzalloc(sizeof(*inst) + sizeof(*ictx), GFP_KERNEL); 5344a49b499SJoy Latten err = -ENOMEM; 5354a49b499SJoy Latten if (!inst) 5364a49b499SJoy Latten goto out_put_cipher; 5374a49b499SJoy Latten 53881c4c35eSHerbert Xu ictx = aead_instance_ctx(inst); 5394a49b499SJoy Latten 54081c4c35eSHerbert Xu err = crypto_init_spawn(&ictx->cipher, cipher, 54181c4c35eSHerbert Xu aead_crypto_instance(inst), 5424a49b499SJoy Latten CRYPTO_ALG_TYPE_MASK); 5434a49b499SJoy Latten if (err) 5444a49b499SJoy Latten goto err_free_inst; 5454a49b499SJoy Latten 54681c4c35eSHerbert Xu crypto_set_skcipher_spawn(&ictx->ctr, aead_crypto_instance(inst)); 547464b93a3SHerbert Xu err = crypto_grab_skcipher2(&ictx->ctr, ctr_name, 0, 5484a49b499SJoy Latten crypto_requires_sync(algt->type, 5494a49b499SJoy Latten algt->mask)); 5504a49b499SJoy Latten if (err) 5514a49b499SJoy Latten goto err_drop_cipher; 5524a49b499SJoy Latten 553464b93a3SHerbert Xu ctr = crypto_spawn_skcipher_alg(&ictx->ctr); 5544a49b499SJoy Latten 5554a49b499SJoy Latten /* Not a stream cipher? */ 5564a49b499SJoy Latten err = -EINVAL; 557464b93a3SHerbert Xu if (ctr->base.cra_blocksize != 1) 5584a49b499SJoy Latten goto err_drop_ctr; 5594a49b499SJoy Latten 5604a49b499SJoy Latten /* We want the real thing! */ 561464b93a3SHerbert Xu if (crypto_skcipher_alg_ivsize(ctr) != 16) 5624a49b499SJoy Latten goto err_drop_ctr; 5634a49b499SJoy Latten 5644a49b499SJoy Latten err = -ENAMETOOLONG; 56581c4c35eSHerbert Xu if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME, 566464b93a3SHerbert Xu "ccm_base(%s,%s)", ctr->base.cra_driver_name, 5674a49b499SJoy Latten cipher->cra_driver_name) >= CRYPTO_MAX_ALG_NAME) 5684a49b499SJoy Latten goto err_drop_ctr; 5694a49b499SJoy Latten 57081c4c35eSHerbert Xu memcpy(inst->alg.base.cra_name, full_name, CRYPTO_MAX_ALG_NAME); 5714a49b499SJoy Latten 572464b93a3SHerbert Xu inst->alg.base.cra_flags = ctr->base.cra_flags & CRYPTO_ALG_ASYNC; 57381c4c35eSHerbert Xu inst->alg.base.cra_priority = (cipher->cra_priority + 574464b93a3SHerbert Xu ctr->base.cra_priority) / 2; 57581c4c35eSHerbert Xu inst->alg.base.cra_blocksize = 1; 57681c4c35eSHerbert Xu inst->alg.base.cra_alignmask = cipher->cra_alignmask | 577464b93a3SHerbert Xu ctr->base.cra_alignmask | 5784a49b499SJoy Latten (__alignof__(u32) - 1); 57981c4c35eSHerbert Xu inst->alg.ivsize = 16; 580464b93a3SHerbert Xu inst->alg.chunksize = crypto_skcipher_alg_chunksize(ctr); 58181c4c35eSHerbert Xu inst->alg.maxauthsize = 16; 58281c4c35eSHerbert Xu inst->alg.base.cra_ctxsize = sizeof(struct crypto_ccm_ctx); 58381c4c35eSHerbert Xu inst->alg.init = crypto_ccm_init_tfm; 58481c4c35eSHerbert Xu inst->alg.exit = crypto_ccm_exit_tfm; 58581c4c35eSHerbert Xu inst->alg.setkey = crypto_ccm_setkey; 58681c4c35eSHerbert Xu inst->alg.setauthsize = crypto_ccm_setauthsize; 58781c4c35eSHerbert Xu inst->alg.encrypt = crypto_ccm_encrypt; 58881c4c35eSHerbert Xu inst->alg.decrypt = crypto_ccm_decrypt; 5894a49b499SJoy Latten 59081c4c35eSHerbert Xu inst->free = crypto_ccm_free; 59181c4c35eSHerbert Xu 59281c4c35eSHerbert Xu err = aead_register_instance(tmpl, inst); 59381c4c35eSHerbert Xu if (err) 59481c4c35eSHerbert Xu goto err_drop_ctr; 59581c4c35eSHerbert Xu 59681c4c35eSHerbert Xu out_put_cipher: 5974a49b499SJoy Latten crypto_mod_put(cipher); 59881c4c35eSHerbert Xu return err; 5994a49b499SJoy Latten 6004a49b499SJoy Latten err_drop_ctr: 6014a49b499SJoy Latten crypto_drop_skcipher(&ictx->ctr); 6024a49b499SJoy Latten err_drop_cipher: 6034a49b499SJoy Latten crypto_drop_spawn(&ictx->cipher); 6044a49b499SJoy Latten err_free_inst: 6054a49b499SJoy Latten kfree(inst); 60681c4c35eSHerbert Xu goto out_put_cipher; 6074a49b499SJoy Latten } 6084a49b499SJoy Latten 60981c4c35eSHerbert Xu static int crypto_ccm_create(struct crypto_template *tmpl, struct rtattr **tb) 6104a49b499SJoy Latten { 6114a49b499SJoy Latten const char *cipher_name; 6124a49b499SJoy Latten char ctr_name[CRYPTO_MAX_ALG_NAME]; 6134a49b499SJoy Latten char full_name[CRYPTO_MAX_ALG_NAME]; 6144a49b499SJoy Latten 6154a49b499SJoy Latten cipher_name = crypto_attr_alg_name(tb[1]); 6164a49b499SJoy Latten if (IS_ERR(cipher_name)) 61781c4c35eSHerbert Xu return PTR_ERR(cipher_name); 6184a49b499SJoy Latten 6194a49b499SJoy Latten if (snprintf(ctr_name, CRYPTO_MAX_ALG_NAME, "ctr(%s)", 6204a49b499SJoy Latten cipher_name) >= CRYPTO_MAX_ALG_NAME) 62181c4c35eSHerbert Xu return -ENAMETOOLONG; 6224a49b499SJoy Latten 6234a49b499SJoy Latten if (snprintf(full_name, CRYPTO_MAX_ALG_NAME, "ccm(%s)", cipher_name) >= 6244a49b499SJoy Latten CRYPTO_MAX_ALG_NAME) 62581c4c35eSHerbert Xu return -ENAMETOOLONG; 6264a49b499SJoy Latten 62781c4c35eSHerbert Xu return crypto_ccm_create_common(tmpl, tb, full_name, ctr_name, 62881c4c35eSHerbert Xu cipher_name); 6294a49b499SJoy Latten } 6304a49b499SJoy Latten 6314a49b499SJoy Latten static struct crypto_template crypto_ccm_tmpl = { 6324a49b499SJoy Latten .name = "ccm", 63381c4c35eSHerbert Xu .create = crypto_ccm_create, 6344a49b499SJoy Latten .module = THIS_MODULE, 6354a49b499SJoy Latten }; 6364a49b499SJoy Latten 63781c4c35eSHerbert Xu static int crypto_ccm_base_create(struct crypto_template *tmpl, 63881c4c35eSHerbert Xu struct rtattr **tb) 6394a49b499SJoy Latten { 6404a49b499SJoy Latten const char *ctr_name; 6414a49b499SJoy Latten const char *cipher_name; 6424a49b499SJoy Latten char full_name[CRYPTO_MAX_ALG_NAME]; 6434a49b499SJoy Latten 6444a49b499SJoy Latten ctr_name = crypto_attr_alg_name(tb[1]); 6454a49b499SJoy Latten if (IS_ERR(ctr_name)) 64681c4c35eSHerbert Xu return PTR_ERR(ctr_name); 6474a49b499SJoy Latten 6484a49b499SJoy Latten cipher_name = crypto_attr_alg_name(tb[2]); 6494a49b499SJoy Latten if (IS_ERR(cipher_name)) 65081c4c35eSHerbert Xu return PTR_ERR(cipher_name); 6514a49b499SJoy Latten 6524a49b499SJoy Latten if (snprintf(full_name, CRYPTO_MAX_ALG_NAME, "ccm_base(%s,%s)", 6534a49b499SJoy Latten ctr_name, cipher_name) >= CRYPTO_MAX_ALG_NAME) 65481c4c35eSHerbert Xu return -ENAMETOOLONG; 6554a49b499SJoy Latten 65681c4c35eSHerbert Xu return crypto_ccm_create_common(tmpl, tb, full_name, ctr_name, 65781c4c35eSHerbert Xu cipher_name); 6584a49b499SJoy Latten } 6594a49b499SJoy Latten 6604a49b499SJoy Latten static struct crypto_template crypto_ccm_base_tmpl = { 6614a49b499SJoy Latten .name = "ccm_base", 66281c4c35eSHerbert Xu .create = crypto_ccm_base_create, 6634a49b499SJoy Latten .module = THIS_MODULE, 6644a49b499SJoy Latten }; 6654a49b499SJoy Latten 6664a49b499SJoy Latten static int crypto_rfc4309_setkey(struct crypto_aead *parent, const u8 *key, 6674a49b499SJoy Latten unsigned int keylen) 6684a49b499SJoy Latten { 6694a49b499SJoy Latten struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(parent); 6704a49b499SJoy Latten struct crypto_aead *child = ctx->child; 6714a49b499SJoy Latten int err; 6724a49b499SJoy Latten 6734a49b499SJoy Latten if (keylen < 3) 6744a49b499SJoy Latten return -EINVAL; 6754a49b499SJoy Latten 6764a49b499SJoy Latten keylen -= 3; 6774a49b499SJoy Latten memcpy(ctx->nonce, key + keylen, 3); 6784a49b499SJoy Latten 6794a49b499SJoy Latten crypto_aead_clear_flags(child, CRYPTO_TFM_REQ_MASK); 6804a49b499SJoy Latten crypto_aead_set_flags(child, crypto_aead_get_flags(parent) & 6814a49b499SJoy Latten CRYPTO_TFM_REQ_MASK); 6824a49b499SJoy Latten err = crypto_aead_setkey(child, key, keylen); 6834a49b499SJoy Latten crypto_aead_set_flags(parent, crypto_aead_get_flags(child) & 6844a49b499SJoy Latten CRYPTO_TFM_RES_MASK); 6854a49b499SJoy Latten 6864a49b499SJoy Latten return err; 6874a49b499SJoy Latten } 6884a49b499SJoy Latten 6894a49b499SJoy Latten static int crypto_rfc4309_setauthsize(struct crypto_aead *parent, 6904a49b499SJoy Latten unsigned int authsize) 6914a49b499SJoy Latten { 6924a49b499SJoy Latten struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(parent); 6934a49b499SJoy Latten 6944a49b499SJoy Latten switch (authsize) { 6954a49b499SJoy Latten case 8: 6964a49b499SJoy Latten case 12: 6974a49b499SJoy Latten case 16: 6984a49b499SJoy Latten break; 6994a49b499SJoy Latten default: 7004a49b499SJoy Latten return -EINVAL; 7014a49b499SJoy Latten } 7024a49b499SJoy Latten 7034a49b499SJoy Latten return crypto_aead_setauthsize(ctx->child, authsize); 7044a49b499SJoy Latten } 7054a49b499SJoy Latten 7064a49b499SJoy Latten static struct aead_request *crypto_rfc4309_crypt(struct aead_request *req) 7074a49b499SJoy Latten { 70881c4c35eSHerbert Xu struct crypto_rfc4309_req_ctx *rctx = aead_request_ctx(req); 70981c4c35eSHerbert Xu struct aead_request *subreq = &rctx->subreq; 7104a49b499SJoy Latten struct crypto_aead *aead = crypto_aead_reqtfm(req); 7114a49b499SJoy Latten struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(aead); 7124a49b499SJoy Latten struct crypto_aead *child = ctx->child; 71381c4c35eSHerbert Xu struct scatterlist *sg; 7144a49b499SJoy Latten u8 *iv = PTR_ALIGN((u8 *)(subreq + 1) + crypto_aead_reqsize(child), 7154a49b499SJoy Latten crypto_aead_alignmask(child) + 1); 7164a49b499SJoy Latten 7174a49b499SJoy Latten /* L' */ 7184a49b499SJoy Latten iv[0] = 3; 7194a49b499SJoy Latten 7204a49b499SJoy Latten memcpy(iv + 1, ctx->nonce, 3); 7214a49b499SJoy Latten memcpy(iv + 4, req->iv, 8); 7224a49b499SJoy Latten 72381c4c35eSHerbert Xu scatterwalk_map_and_copy(iv + 16, req->src, 0, req->assoclen - 8, 0); 72481c4c35eSHerbert Xu 72581c4c35eSHerbert Xu sg_init_table(rctx->src, 3); 72681c4c35eSHerbert Xu sg_set_buf(rctx->src, iv + 16, req->assoclen - 8); 72781c4c35eSHerbert Xu sg = scatterwalk_ffwd(rctx->src + 1, req->src, req->assoclen); 72881c4c35eSHerbert Xu if (sg != rctx->src + 1) 72981c4c35eSHerbert Xu sg_chain(rctx->src, 2, sg); 73081c4c35eSHerbert Xu 73181c4c35eSHerbert Xu if (req->src != req->dst) { 73281c4c35eSHerbert Xu sg_init_table(rctx->dst, 3); 73381c4c35eSHerbert Xu sg_set_buf(rctx->dst, iv + 16, req->assoclen - 8); 73481c4c35eSHerbert Xu sg = scatterwalk_ffwd(rctx->dst + 1, req->dst, req->assoclen); 73581c4c35eSHerbert Xu if (sg != rctx->dst + 1) 73681c4c35eSHerbert Xu sg_chain(rctx->dst, 2, sg); 73781c4c35eSHerbert Xu } 73881c4c35eSHerbert Xu 7394a49b499SJoy Latten aead_request_set_tfm(subreq, child); 7404a49b499SJoy Latten aead_request_set_callback(subreq, req->base.flags, req->base.complete, 7414a49b499SJoy Latten req->base.data); 74281c4c35eSHerbert Xu aead_request_set_crypt(subreq, rctx->src, 74381c4c35eSHerbert Xu req->src == req->dst ? rctx->src : rctx->dst, 74481c4c35eSHerbert Xu req->cryptlen, iv); 74581c4c35eSHerbert Xu aead_request_set_ad(subreq, req->assoclen - 8); 7464a49b499SJoy Latten 7474a49b499SJoy Latten return subreq; 7484a49b499SJoy Latten } 7494a49b499SJoy Latten 7504a49b499SJoy Latten static int crypto_rfc4309_encrypt(struct aead_request *req) 7514a49b499SJoy Latten { 75281c4c35eSHerbert Xu if (req->assoclen != 16 && req->assoclen != 20) 75381c4c35eSHerbert Xu return -EINVAL; 75481c4c35eSHerbert Xu 7554a49b499SJoy Latten req = crypto_rfc4309_crypt(req); 7564a49b499SJoy Latten 7574a49b499SJoy Latten return crypto_aead_encrypt(req); 7584a49b499SJoy Latten } 7594a49b499SJoy Latten 7604a49b499SJoy Latten static int crypto_rfc4309_decrypt(struct aead_request *req) 7614a49b499SJoy Latten { 76281c4c35eSHerbert Xu if (req->assoclen != 16 && req->assoclen != 20) 76381c4c35eSHerbert Xu return -EINVAL; 76481c4c35eSHerbert Xu 7654a49b499SJoy Latten req = crypto_rfc4309_crypt(req); 7664a49b499SJoy Latten 7674a49b499SJoy Latten return crypto_aead_decrypt(req); 7684a49b499SJoy Latten } 7694a49b499SJoy Latten 77081c4c35eSHerbert Xu static int crypto_rfc4309_init_tfm(struct crypto_aead *tfm) 7714a49b499SJoy Latten { 77281c4c35eSHerbert Xu struct aead_instance *inst = aead_alg_instance(tfm); 77381c4c35eSHerbert Xu struct crypto_aead_spawn *spawn = aead_instance_ctx(inst); 77481c4c35eSHerbert Xu struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(tfm); 7754a49b499SJoy Latten struct crypto_aead *aead; 7764a49b499SJoy Latten unsigned long align; 7774a49b499SJoy Latten 7784a49b499SJoy Latten aead = crypto_spawn_aead(spawn); 7794a49b499SJoy Latten if (IS_ERR(aead)) 7804a49b499SJoy Latten return PTR_ERR(aead); 7814a49b499SJoy Latten 7824a49b499SJoy Latten ctx->child = aead; 7834a49b499SJoy Latten 7844a49b499SJoy Latten align = crypto_aead_alignmask(aead); 7854a49b499SJoy Latten align &= ~(crypto_tfm_ctx_alignment() - 1); 78681c4c35eSHerbert Xu crypto_aead_set_reqsize( 78781c4c35eSHerbert Xu tfm, 78881c4c35eSHerbert Xu sizeof(struct crypto_rfc4309_req_ctx) + 7892c221ad3SHerbert Xu ALIGN(crypto_aead_reqsize(aead), crypto_tfm_ctx_alignment()) + 79081c4c35eSHerbert Xu align + 32); 7914a49b499SJoy Latten 7924a49b499SJoy Latten return 0; 7934a49b499SJoy Latten } 7944a49b499SJoy Latten 79581c4c35eSHerbert Xu static void crypto_rfc4309_exit_tfm(struct crypto_aead *tfm) 7964a49b499SJoy Latten { 79781c4c35eSHerbert Xu struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(tfm); 7984a49b499SJoy Latten 7994a49b499SJoy Latten crypto_free_aead(ctx->child); 8004a49b499SJoy Latten } 8014a49b499SJoy Latten 80281c4c35eSHerbert Xu static void crypto_rfc4309_free(struct aead_instance *inst) 80381c4c35eSHerbert Xu { 80481c4c35eSHerbert Xu crypto_drop_aead(aead_instance_ctx(inst)); 80581c4c35eSHerbert Xu kfree(inst); 80681c4c35eSHerbert Xu } 80781c4c35eSHerbert Xu 80881c4c35eSHerbert Xu static int crypto_rfc4309_create(struct crypto_template *tmpl, 80981c4c35eSHerbert Xu struct rtattr **tb) 8104a49b499SJoy Latten { 8114a49b499SJoy Latten struct crypto_attr_type *algt; 81281c4c35eSHerbert Xu struct aead_instance *inst; 8134a49b499SJoy Latten struct crypto_aead_spawn *spawn; 81481c4c35eSHerbert Xu struct aead_alg *alg; 8154a49b499SJoy Latten const char *ccm_name; 8164a49b499SJoy Latten int err; 8174a49b499SJoy Latten 8184a49b499SJoy Latten algt = crypto_get_attr_type(tb); 8194a49b499SJoy Latten if (IS_ERR(algt)) 82081c4c35eSHerbert Xu return PTR_ERR(algt); 8214a49b499SJoy Latten 8225e4b8c1fSHerbert Xu if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask) 82381c4c35eSHerbert Xu return -EINVAL; 8244a49b499SJoy Latten 8254a49b499SJoy Latten ccm_name = crypto_attr_alg_name(tb[1]); 8264a49b499SJoy Latten if (IS_ERR(ccm_name)) 82781c4c35eSHerbert Xu return PTR_ERR(ccm_name); 8284a49b499SJoy Latten 8294a49b499SJoy Latten inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL); 8304a49b499SJoy Latten if (!inst) 83181c4c35eSHerbert Xu return -ENOMEM; 8324a49b499SJoy Latten 83381c4c35eSHerbert Xu spawn = aead_instance_ctx(inst); 83481c4c35eSHerbert Xu crypto_set_aead_spawn(spawn, aead_crypto_instance(inst)); 8354a49b499SJoy Latten err = crypto_grab_aead(spawn, ccm_name, 0, 8364a49b499SJoy Latten crypto_requires_sync(algt->type, algt->mask)); 8374a49b499SJoy Latten if (err) 8384a49b499SJoy Latten goto out_free_inst; 8394a49b499SJoy Latten 84081c4c35eSHerbert Xu alg = crypto_spawn_aead_alg(spawn); 8414a49b499SJoy Latten 8424a49b499SJoy Latten err = -EINVAL; 8434a49b499SJoy Latten 8444a49b499SJoy Latten /* We only support 16-byte blocks. */ 84581c4c35eSHerbert Xu if (crypto_aead_alg_ivsize(alg) != 16) 8464a49b499SJoy Latten goto out_drop_alg; 8474a49b499SJoy Latten 8484a49b499SJoy Latten /* Not a stream cipher? */ 84981c4c35eSHerbert Xu if (alg->base.cra_blocksize != 1) 8504a49b499SJoy Latten goto out_drop_alg; 8514a49b499SJoy Latten 8524a49b499SJoy Latten err = -ENAMETOOLONG; 85381c4c35eSHerbert Xu if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME, 85481c4c35eSHerbert Xu "rfc4309(%s)", alg->base.cra_name) >= 85581c4c35eSHerbert Xu CRYPTO_MAX_ALG_NAME || 85681c4c35eSHerbert Xu snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME, 85781c4c35eSHerbert Xu "rfc4309(%s)", alg->base.cra_driver_name) >= 8584a49b499SJoy Latten CRYPTO_MAX_ALG_NAME) 8594a49b499SJoy Latten goto out_drop_alg; 8604a49b499SJoy Latten 86181c4c35eSHerbert Xu inst->alg.base.cra_flags = alg->base.cra_flags & CRYPTO_ALG_ASYNC; 86281c4c35eSHerbert Xu inst->alg.base.cra_priority = alg->base.cra_priority; 86381c4c35eSHerbert Xu inst->alg.base.cra_blocksize = 1; 86481c4c35eSHerbert Xu inst->alg.base.cra_alignmask = alg->base.cra_alignmask; 8654a49b499SJoy Latten 86681c4c35eSHerbert Xu inst->alg.ivsize = 8; 867464b93a3SHerbert Xu inst->alg.chunksize = crypto_aead_alg_chunksize(alg); 86881c4c35eSHerbert Xu inst->alg.maxauthsize = 16; 8694a49b499SJoy Latten 87081c4c35eSHerbert Xu inst->alg.base.cra_ctxsize = sizeof(struct crypto_rfc4309_ctx); 8714a49b499SJoy Latten 87281c4c35eSHerbert Xu inst->alg.init = crypto_rfc4309_init_tfm; 87381c4c35eSHerbert Xu inst->alg.exit = crypto_rfc4309_exit_tfm; 8744a49b499SJoy Latten 87581c4c35eSHerbert Xu inst->alg.setkey = crypto_rfc4309_setkey; 87681c4c35eSHerbert Xu inst->alg.setauthsize = crypto_rfc4309_setauthsize; 87781c4c35eSHerbert Xu inst->alg.encrypt = crypto_rfc4309_encrypt; 87881c4c35eSHerbert Xu inst->alg.decrypt = crypto_rfc4309_decrypt; 8794a49b499SJoy Latten 88081c4c35eSHerbert Xu inst->free = crypto_rfc4309_free; 88181c4c35eSHerbert Xu 88281c4c35eSHerbert Xu err = aead_register_instance(tmpl, inst); 88381c4c35eSHerbert Xu if (err) 88481c4c35eSHerbert Xu goto out_drop_alg; 8854a49b499SJoy Latten 8864a49b499SJoy Latten out: 88781c4c35eSHerbert Xu return err; 8884a49b499SJoy Latten 8894a49b499SJoy Latten out_drop_alg: 8904a49b499SJoy Latten crypto_drop_aead(spawn); 8914a49b499SJoy Latten out_free_inst: 8924a49b499SJoy Latten kfree(inst); 8934a49b499SJoy Latten goto out; 8944a49b499SJoy Latten } 8954a49b499SJoy Latten 8964a49b499SJoy Latten static struct crypto_template crypto_rfc4309_tmpl = { 8974a49b499SJoy Latten .name = "rfc4309", 89881c4c35eSHerbert Xu .create = crypto_rfc4309_create, 8994a49b499SJoy Latten .module = THIS_MODULE, 9004a49b499SJoy Latten }; 9014a49b499SJoy Latten 9024a49b499SJoy Latten static int __init crypto_ccm_module_init(void) 9034a49b499SJoy Latten { 9044a49b499SJoy Latten int err; 9054a49b499SJoy Latten 9064a49b499SJoy Latten err = crypto_register_template(&crypto_ccm_base_tmpl); 9074a49b499SJoy Latten if (err) 9084a49b499SJoy Latten goto out; 9094a49b499SJoy Latten 9104a49b499SJoy Latten err = crypto_register_template(&crypto_ccm_tmpl); 9114a49b499SJoy Latten if (err) 9124a49b499SJoy Latten goto out_undo_base; 9134a49b499SJoy Latten 9144a49b499SJoy Latten err = crypto_register_template(&crypto_rfc4309_tmpl); 9154a49b499SJoy Latten if (err) 9164a49b499SJoy Latten goto out_undo_ccm; 9174a49b499SJoy Latten 9184a49b499SJoy Latten out: 9194a49b499SJoy Latten return err; 9204a49b499SJoy Latten 9214a49b499SJoy Latten out_undo_ccm: 9224a49b499SJoy Latten crypto_unregister_template(&crypto_ccm_tmpl); 9234a49b499SJoy Latten out_undo_base: 9244a49b499SJoy Latten crypto_unregister_template(&crypto_ccm_base_tmpl); 9254a49b499SJoy Latten goto out; 9264a49b499SJoy Latten } 9274a49b499SJoy Latten 9284a49b499SJoy Latten static void __exit crypto_ccm_module_exit(void) 9294a49b499SJoy Latten { 9304a49b499SJoy Latten crypto_unregister_template(&crypto_rfc4309_tmpl); 9314a49b499SJoy Latten crypto_unregister_template(&crypto_ccm_tmpl); 9324a49b499SJoy Latten crypto_unregister_template(&crypto_ccm_base_tmpl); 9334a49b499SJoy Latten } 9344a49b499SJoy Latten 9354a49b499SJoy Latten module_init(crypto_ccm_module_init); 9364a49b499SJoy Latten module_exit(crypto_ccm_module_exit); 9374a49b499SJoy Latten 9384a49b499SJoy Latten MODULE_LICENSE("GPL"); 9394a49b499SJoy Latten MODULE_DESCRIPTION("Counter with CBC MAC"); 9405d26a105SKees Cook MODULE_ALIAS_CRYPTO("ccm_base"); 9415d26a105SKees Cook MODULE_ALIAS_CRYPTO("rfc4309"); 9424943ba16SKees Cook MODULE_ALIAS_CRYPTO("ccm"); 943