1*1da177e4SLinus Torvalds /* 2*1da177e4SLinus Torvalds * Cryptographic API. 3*1da177e4SLinus Torvalds * 4*1da177e4SLinus Torvalds * Cipher operations. 5*1da177e4SLinus Torvalds * 6*1da177e4SLinus Torvalds * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> 7*1da177e4SLinus Torvalds * 8*1da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or modify it 9*1da177e4SLinus Torvalds * under the terms of the GNU General Public License as published by the Free 10*1da177e4SLinus Torvalds * Software Foundation; either version 2 of the License, or (at your option) 11*1da177e4SLinus Torvalds * any later version. 12*1da177e4SLinus Torvalds * 13*1da177e4SLinus Torvalds */ 14*1da177e4SLinus Torvalds #include <linux/compiler.h> 15*1da177e4SLinus Torvalds #include <linux/kernel.h> 16*1da177e4SLinus Torvalds #include <linux/crypto.h> 17*1da177e4SLinus Torvalds #include <linux/errno.h> 18*1da177e4SLinus Torvalds #include <linux/mm.h> 19*1da177e4SLinus Torvalds #include <linux/slab.h> 20*1da177e4SLinus Torvalds #include <linux/string.h> 21*1da177e4SLinus Torvalds #include <asm/scatterlist.h> 22*1da177e4SLinus Torvalds #include "internal.h" 23*1da177e4SLinus Torvalds #include "scatterwalk.h" 24*1da177e4SLinus Torvalds 25*1da177e4SLinus Torvalds typedef void (cryptfn_t)(void *, u8 *, const u8 *); 26*1da177e4SLinus Torvalds typedef void (procfn_t)(struct crypto_tfm *, u8 *, 27*1da177e4SLinus Torvalds u8*, cryptfn_t, void *); 28*1da177e4SLinus Torvalds 29*1da177e4SLinus Torvalds static inline void xor_64(u8 *a, const u8 *b) 30*1da177e4SLinus Torvalds { 31*1da177e4SLinus Torvalds ((u32 *)a)[0] ^= ((u32 *)b)[0]; 32*1da177e4SLinus Torvalds ((u32 *)a)[1] ^= ((u32 *)b)[1]; 33*1da177e4SLinus Torvalds } 34*1da177e4SLinus Torvalds 35*1da177e4SLinus Torvalds static inline void xor_128(u8 *a, const u8 *b) 36*1da177e4SLinus Torvalds { 37*1da177e4SLinus Torvalds ((u32 *)a)[0] ^= ((u32 *)b)[0]; 38*1da177e4SLinus Torvalds ((u32 *)a)[1] ^= ((u32 *)b)[1]; 39*1da177e4SLinus Torvalds ((u32 *)a)[2] ^= ((u32 *)b)[2]; 40*1da177e4SLinus Torvalds ((u32 *)a)[3] ^= ((u32 *)b)[3]; 41*1da177e4SLinus Torvalds } 42*1da177e4SLinus Torvalds 43*1da177e4SLinus Torvalds static inline void *prepare_src(struct scatter_walk *walk, int bsize, 44*1da177e4SLinus Torvalds void *tmp, int in_place) 45*1da177e4SLinus Torvalds { 46*1da177e4SLinus Torvalds void *src = walk->data; 47*1da177e4SLinus Torvalds int n = bsize; 48*1da177e4SLinus Torvalds 49*1da177e4SLinus Torvalds if (unlikely(scatterwalk_across_pages(walk, bsize))) { 50*1da177e4SLinus Torvalds src = tmp; 51*1da177e4SLinus Torvalds n = scatterwalk_copychunks(src, walk, bsize, 0); 52*1da177e4SLinus Torvalds } 53*1da177e4SLinus Torvalds scatterwalk_advance(walk, n); 54*1da177e4SLinus Torvalds return src; 55*1da177e4SLinus Torvalds } 56*1da177e4SLinus Torvalds 57*1da177e4SLinus Torvalds static inline void *prepare_dst(struct scatter_walk *walk, int bsize, 58*1da177e4SLinus Torvalds void *tmp, int in_place) 59*1da177e4SLinus Torvalds { 60*1da177e4SLinus Torvalds void *dst = walk->data; 61*1da177e4SLinus Torvalds 62*1da177e4SLinus Torvalds if (unlikely(scatterwalk_across_pages(walk, bsize)) || in_place) 63*1da177e4SLinus Torvalds dst = tmp; 64*1da177e4SLinus Torvalds return dst; 65*1da177e4SLinus Torvalds } 66*1da177e4SLinus Torvalds 67*1da177e4SLinus Torvalds static inline void complete_src(struct scatter_walk *walk, int bsize, 68*1da177e4SLinus Torvalds void *src, int in_place) 69*1da177e4SLinus Torvalds { 70*1da177e4SLinus Torvalds } 71*1da177e4SLinus Torvalds 72*1da177e4SLinus Torvalds static inline void complete_dst(struct scatter_walk *walk, int bsize, 73*1da177e4SLinus Torvalds void *dst, int in_place) 74*1da177e4SLinus Torvalds { 75*1da177e4SLinus Torvalds int n = bsize; 76*1da177e4SLinus Torvalds 77*1da177e4SLinus Torvalds if (unlikely(scatterwalk_across_pages(walk, bsize))) 78*1da177e4SLinus Torvalds n = scatterwalk_copychunks(dst, walk, bsize, 1); 79*1da177e4SLinus Torvalds else if (in_place) 80*1da177e4SLinus Torvalds memcpy(walk->data, dst, bsize); 81*1da177e4SLinus Torvalds scatterwalk_advance(walk, n); 82*1da177e4SLinus Torvalds } 83*1da177e4SLinus Torvalds 84*1da177e4SLinus Torvalds /* 85*1da177e4SLinus Torvalds * Generic encrypt/decrypt wrapper for ciphers, handles operations across 86*1da177e4SLinus Torvalds * multiple page boundaries by using temporary blocks. In user context, 87*1da177e4SLinus Torvalds * the kernel is given a chance to schedule us once per block. 88*1da177e4SLinus Torvalds */ 89*1da177e4SLinus Torvalds static int crypt(struct crypto_tfm *tfm, 90*1da177e4SLinus Torvalds struct scatterlist *dst, 91*1da177e4SLinus Torvalds struct scatterlist *src, 92*1da177e4SLinus Torvalds unsigned int nbytes, cryptfn_t crfn, 93*1da177e4SLinus Torvalds procfn_t prfn, void *info) 94*1da177e4SLinus Torvalds { 95*1da177e4SLinus Torvalds struct scatter_walk walk_in, walk_out; 96*1da177e4SLinus Torvalds const unsigned int bsize = crypto_tfm_alg_blocksize(tfm); 97*1da177e4SLinus Torvalds u8 tmp_src[bsize]; 98*1da177e4SLinus Torvalds u8 tmp_dst[bsize]; 99*1da177e4SLinus Torvalds 100*1da177e4SLinus Torvalds if (!nbytes) 101*1da177e4SLinus Torvalds return 0; 102*1da177e4SLinus Torvalds 103*1da177e4SLinus Torvalds if (nbytes % bsize) { 104*1da177e4SLinus Torvalds tfm->crt_flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN; 105*1da177e4SLinus Torvalds return -EINVAL; 106*1da177e4SLinus Torvalds } 107*1da177e4SLinus Torvalds 108*1da177e4SLinus Torvalds scatterwalk_start(&walk_in, src); 109*1da177e4SLinus Torvalds scatterwalk_start(&walk_out, dst); 110*1da177e4SLinus Torvalds 111*1da177e4SLinus Torvalds for(;;) { 112*1da177e4SLinus Torvalds u8 *src_p, *dst_p; 113*1da177e4SLinus Torvalds int in_place; 114*1da177e4SLinus Torvalds 115*1da177e4SLinus Torvalds scatterwalk_map(&walk_in, 0); 116*1da177e4SLinus Torvalds scatterwalk_map(&walk_out, 1); 117*1da177e4SLinus Torvalds 118*1da177e4SLinus Torvalds in_place = scatterwalk_samebuf(&walk_in, &walk_out); 119*1da177e4SLinus Torvalds 120*1da177e4SLinus Torvalds do { 121*1da177e4SLinus Torvalds src_p = prepare_src(&walk_in, bsize, tmp_src, 122*1da177e4SLinus Torvalds in_place); 123*1da177e4SLinus Torvalds dst_p = prepare_dst(&walk_out, bsize, tmp_dst, 124*1da177e4SLinus Torvalds in_place); 125*1da177e4SLinus Torvalds 126*1da177e4SLinus Torvalds prfn(tfm, dst_p, src_p, crfn, info); 127*1da177e4SLinus Torvalds 128*1da177e4SLinus Torvalds complete_src(&walk_in, bsize, src_p, in_place); 129*1da177e4SLinus Torvalds complete_dst(&walk_out, bsize, dst_p, in_place); 130*1da177e4SLinus Torvalds 131*1da177e4SLinus Torvalds nbytes -= bsize; 132*1da177e4SLinus Torvalds } while (nbytes && 133*1da177e4SLinus Torvalds !scatterwalk_across_pages(&walk_in, bsize) && 134*1da177e4SLinus Torvalds !scatterwalk_across_pages(&walk_out, bsize)); 135*1da177e4SLinus Torvalds 136*1da177e4SLinus Torvalds scatterwalk_done(&walk_in, 0, nbytes); 137*1da177e4SLinus Torvalds scatterwalk_done(&walk_out, 1, nbytes); 138*1da177e4SLinus Torvalds 139*1da177e4SLinus Torvalds if (!nbytes) 140*1da177e4SLinus Torvalds return 0; 141*1da177e4SLinus Torvalds 142*1da177e4SLinus Torvalds crypto_yield(tfm); 143*1da177e4SLinus Torvalds } 144*1da177e4SLinus Torvalds } 145*1da177e4SLinus Torvalds 146*1da177e4SLinus Torvalds static void cbc_process_encrypt(struct crypto_tfm *tfm, u8 *dst, u8 *src, 147*1da177e4SLinus Torvalds cryptfn_t fn, void *info) 148*1da177e4SLinus Torvalds { 149*1da177e4SLinus Torvalds u8 *iv = info; 150*1da177e4SLinus Torvalds 151*1da177e4SLinus Torvalds tfm->crt_u.cipher.cit_xor_block(iv, src); 152*1da177e4SLinus Torvalds fn(crypto_tfm_ctx(tfm), dst, iv); 153*1da177e4SLinus Torvalds memcpy(iv, dst, crypto_tfm_alg_blocksize(tfm)); 154*1da177e4SLinus Torvalds } 155*1da177e4SLinus Torvalds 156*1da177e4SLinus Torvalds static void cbc_process_decrypt(struct crypto_tfm *tfm, u8 *dst, u8 *src, 157*1da177e4SLinus Torvalds cryptfn_t fn, void *info) 158*1da177e4SLinus Torvalds { 159*1da177e4SLinus Torvalds u8 *iv = info; 160*1da177e4SLinus Torvalds 161*1da177e4SLinus Torvalds fn(crypto_tfm_ctx(tfm), dst, src); 162*1da177e4SLinus Torvalds tfm->crt_u.cipher.cit_xor_block(dst, iv); 163*1da177e4SLinus Torvalds memcpy(iv, src, crypto_tfm_alg_blocksize(tfm)); 164*1da177e4SLinus Torvalds } 165*1da177e4SLinus Torvalds 166*1da177e4SLinus Torvalds static void ecb_process(struct crypto_tfm *tfm, u8 *dst, u8 *src, 167*1da177e4SLinus Torvalds cryptfn_t fn, void *info) 168*1da177e4SLinus Torvalds { 169*1da177e4SLinus Torvalds fn(crypto_tfm_ctx(tfm), dst, src); 170*1da177e4SLinus Torvalds } 171*1da177e4SLinus Torvalds 172*1da177e4SLinus Torvalds static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) 173*1da177e4SLinus Torvalds { 174*1da177e4SLinus Torvalds struct cipher_alg *cia = &tfm->__crt_alg->cra_cipher; 175*1da177e4SLinus Torvalds 176*1da177e4SLinus Torvalds if (keylen < cia->cia_min_keysize || keylen > cia->cia_max_keysize) { 177*1da177e4SLinus Torvalds tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; 178*1da177e4SLinus Torvalds return -EINVAL; 179*1da177e4SLinus Torvalds } else 180*1da177e4SLinus Torvalds return cia->cia_setkey(crypto_tfm_ctx(tfm), key, keylen, 181*1da177e4SLinus Torvalds &tfm->crt_flags); 182*1da177e4SLinus Torvalds } 183*1da177e4SLinus Torvalds 184*1da177e4SLinus Torvalds static int ecb_encrypt(struct crypto_tfm *tfm, 185*1da177e4SLinus Torvalds struct scatterlist *dst, 186*1da177e4SLinus Torvalds struct scatterlist *src, unsigned int nbytes) 187*1da177e4SLinus Torvalds { 188*1da177e4SLinus Torvalds return crypt(tfm, dst, src, nbytes, 189*1da177e4SLinus Torvalds tfm->__crt_alg->cra_cipher.cia_encrypt, 190*1da177e4SLinus Torvalds ecb_process, NULL); 191*1da177e4SLinus Torvalds } 192*1da177e4SLinus Torvalds 193*1da177e4SLinus Torvalds static int ecb_decrypt(struct crypto_tfm *tfm, 194*1da177e4SLinus Torvalds struct scatterlist *dst, 195*1da177e4SLinus Torvalds struct scatterlist *src, 196*1da177e4SLinus Torvalds unsigned int nbytes) 197*1da177e4SLinus Torvalds { 198*1da177e4SLinus Torvalds return crypt(tfm, dst, src, nbytes, 199*1da177e4SLinus Torvalds tfm->__crt_alg->cra_cipher.cia_decrypt, 200*1da177e4SLinus Torvalds ecb_process, NULL); 201*1da177e4SLinus Torvalds } 202*1da177e4SLinus Torvalds 203*1da177e4SLinus Torvalds static int cbc_encrypt(struct crypto_tfm *tfm, 204*1da177e4SLinus Torvalds struct scatterlist *dst, 205*1da177e4SLinus Torvalds struct scatterlist *src, 206*1da177e4SLinus Torvalds unsigned int nbytes) 207*1da177e4SLinus Torvalds { 208*1da177e4SLinus Torvalds return crypt(tfm, dst, src, nbytes, 209*1da177e4SLinus Torvalds tfm->__crt_alg->cra_cipher.cia_encrypt, 210*1da177e4SLinus Torvalds cbc_process_encrypt, tfm->crt_cipher.cit_iv); 211*1da177e4SLinus Torvalds } 212*1da177e4SLinus Torvalds 213*1da177e4SLinus Torvalds static int cbc_encrypt_iv(struct crypto_tfm *tfm, 214*1da177e4SLinus Torvalds struct scatterlist *dst, 215*1da177e4SLinus Torvalds struct scatterlist *src, 216*1da177e4SLinus Torvalds unsigned int nbytes, u8 *iv) 217*1da177e4SLinus Torvalds { 218*1da177e4SLinus Torvalds return crypt(tfm, dst, src, nbytes, 219*1da177e4SLinus Torvalds tfm->__crt_alg->cra_cipher.cia_encrypt, 220*1da177e4SLinus Torvalds cbc_process_encrypt, iv); 221*1da177e4SLinus Torvalds } 222*1da177e4SLinus Torvalds 223*1da177e4SLinus Torvalds static int cbc_decrypt(struct crypto_tfm *tfm, 224*1da177e4SLinus Torvalds struct scatterlist *dst, 225*1da177e4SLinus Torvalds struct scatterlist *src, 226*1da177e4SLinus Torvalds unsigned int nbytes) 227*1da177e4SLinus Torvalds { 228*1da177e4SLinus Torvalds return crypt(tfm, dst, src, nbytes, 229*1da177e4SLinus Torvalds tfm->__crt_alg->cra_cipher.cia_decrypt, 230*1da177e4SLinus Torvalds cbc_process_decrypt, tfm->crt_cipher.cit_iv); 231*1da177e4SLinus Torvalds } 232*1da177e4SLinus Torvalds 233*1da177e4SLinus Torvalds static int cbc_decrypt_iv(struct crypto_tfm *tfm, 234*1da177e4SLinus Torvalds struct scatterlist *dst, 235*1da177e4SLinus Torvalds struct scatterlist *src, 236*1da177e4SLinus Torvalds unsigned int nbytes, u8 *iv) 237*1da177e4SLinus Torvalds { 238*1da177e4SLinus Torvalds return crypt(tfm, dst, src, nbytes, 239*1da177e4SLinus Torvalds tfm->__crt_alg->cra_cipher.cia_decrypt, 240*1da177e4SLinus Torvalds cbc_process_decrypt, iv); 241*1da177e4SLinus Torvalds } 242*1da177e4SLinus Torvalds 243*1da177e4SLinus Torvalds static int nocrypt(struct crypto_tfm *tfm, 244*1da177e4SLinus Torvalds struct scatterlist *dst, 245*1da177e4SLinus Torvalds struct scatterlist *src, 246*1da177e4SLinus Torvalds unsigned int nbytes) 247*1da177e4SLinus Torvalds { 248*1da177e4SLinus Torvalds return -ENOSYS; 249*1da177e4SLinus Torvalds } 250*1da177e4SLinus Torvalds 251*1da177e4SLinus Torvalds static int nocrypt_iv(struct crypto_tfm *tfm, 252*1da177e4SLinus Torvalds struct scatterlist *dst, 253*1da177e4SLinus Torvalds struct scatterlist *src, 254*1da177e4SLinus Torvalds unsigned int nbytes, u8 *iv) 255*1da177e4SLinus Torvalds { 256*1da177e4SLinus Torvalds return -ENOSYS; 257*1da177e4SLinus Torvalds } 258*1da177e4SLinus Torvalds 259*1da177e4SLinus Torvalds int crypto_init_cipher_flags(struct crypto_tfm *tfm, u32 flags) 260*1da177e4SLinus Torvalds { 261*1da177e4SLinus Torvalds u32 mode = flags & CRYPTO_TFM_MODE_MASK; 262*1da177e4SLinus Torvalds 263*1da177e4SLinus Torvalds tfm->crt_cipher.cit_mode = mode ? mode : CRYPTO_TFM_MODE_ECB; 264*1da177e4SLinus Torvalds if (flags & CRYPTO_TFM_REQ_WEAK_KEY) 265*1da177e4SLinus Torvalds tfm->crt_flags = CRYPTO_TFM_REQ_WEAK_KEY; 266*1da177e4SLinus Torvalds 267*1da177e4SLinus Torvalds return 0; 268*1da177e4SLinus Torvalds } 269*1da177e4SLinus Torvalds 270*1da177e4SLinus Torvalds int crypto_init_cipher_ops(struct crypto_tfm *tfm) 271*1da177e4SLinus Torvalds { 272*1da177e4SLinus Torvalds int ret = 0; 273*1da177e4SLinus Torvalds struct cipher_tfm *ops = &tfm->crt_cipher; 274*1da177e4SLinus Torvalds 275*1da177e4SLinus Torvalds ops->cit_setkey = setkey; 276*1da177e4SLinus Torvalds 277*1da177e4SLinus Torvalds switch (tfm->crt_cipher.cit_mode) { 278*1da177e4SLinus Torvalds case CRYPTO_TFM_MODE_ECB: 279*1da177e4SLinus Torvalds ops->cit_encrypt = ecb_encrypt; 280*1da177e4SLinus Torvalds ops->cit_decrypt = ecb_decrypt; 281*1da177e4SLinus Torvalds break; 282*1da177e4SLinus Torvalds 283*1da177e4SLinus Torvalds case CRYPTO_TFM_MODE_CBC: 284*1da177e4SLinus Torvalds ops->cit_encrypt = cbc_encrypt; 285*1da177e4SLinus Torvalds ops->cit_decrypt = cbc_decrypt; 286*1da177e4SLinus Torvalds ops->cit_encrypt_iv = cbc_encrypt_iv; 287*1da177e4SLinus Torvalds ops->cit_decrypt_iv = cbc_decrypt_iv; 288*1da177e4SLinus Torvalds break; 289*1da177e4SLinus Torvalds 290*1da177e4SLinus Torvalds case CRYPTO_TFM_MODE_CFB: 291*1da177e4SLinus Torvalds ops->cit_encrypt = nocrypt; 292*1da177e4SLinus Torvalds ops->cit_decrypt = nocrypt; 293*1da177e4SLinus Torvalds ops->cit_encrypt_iv = nocrypt_iv; 294*1da177e4SLinus Torvalds ops->cit_decrypt_iv = nocrypt_iv; 295*1da177e4SLinus Torvalds break; 296*1da177e4SLinus Torvalds 297*1da177e4SLinus Torvalds case CRYPTO_TFM_MODE_CTR: 298*1da177e4SLinus Torvalds ops->cit_encrypt = nocrypt; 299*1da177e4SLinus Torvalds ops->cit_decrypt = nocrypt; 300*1da177e4SLinus Torvalds ops->cit_encrypt_iv = nocrypt_iv; 301*1da177e4SLinus Torvalds ops->cit_decrypt_iv = nocrypt_iv; 302*1da177e4SLinus Torvalds break; 303*1da177e4SLinus Torvalds 304*1da177e4SLinus Torvalds default: 305*1da177e4SLinus Torvalds BUG(); 306*1da177e4SLinus Torvalds } 307*1da177e4SLinus Torvalds 308*1da177e4SLinus Torvalds if (ops->cit_mode == CRYPTO_TFM_MODE_CBC) { 309*1da177e4SLinus Torvalds 310*1da177e4SLinus Torvalds switch (crypto_tfm_alg_blocksize(tfm)) { 311*1da177e4SLinus Torvalds case 8: 312*1da177e4SLinus Torvalds ops->cit_xor_block = xor_64; 313*1da177e4SLinus Torvalds break; 314*1da177e4SLinus Torvalds 315*1da177e4SLinus Torvalds case 16: 316*1da177e4SLinus Torvalds ops->cit_xor_block = xor_128; 317*1da177e4SLinus Torvalds break; 318*1da177e4SLinus Torvalds 319*1da177e4SLinus Torvalds default: 320*1da177e4SLinus Torvalds printk(KERN_WARNING "%s: block size %u not supported\n", 321*1da177e4SLinus Torvalds crypto_tfm_alg_name(tfm), 322*1da177e4SLinus Torvalds crypto_tfm_alg_blocksize(tfm)); 323*1da177e4SLinus Torvalds ret = -EINVAL; 324*1da177e4SLinus Torvalds goto out; 325*1da177e4SLinus Torvalds } 326*1da177e4SLinus Torvalds 327*1da177e4SLinus Torvalds ops->cit_ivsize = crypto_tfm_alg_blocksize(tfm); 328*1da177e4SLinus Torvalds ops->cit_iv = kmalloc(ops->cit_ivsize, GFP_KERNEL); 329*1da177e4SLinus Torvalds if (ops->cit_iv == NULL) 330*1da177e4SLinus Torvalds ret = -ENOMEM; 331*1da177e4SLinus Torvalds } 332*1da177e4SLinus Torvalds 333*1da177e4SLinus Torvalds out: 334*1da177e4SLinus Torvalds return ret; 335*1da177e4SLinus Torvalds } 336*1da177e4SLinus Torvalds 337*1da177e4SLinus Torvalds void crypto_exit_cipher_ops(struct crypto_tfm *tfm) 338*1da177e4SLinus Torvalds { 339*1da177e4SLinus Torvalds if (tfm->crt_cipher.cit_iv) 340*1da177e4SLinus Torvalds kfree(tfm->crt_cipher.cit_iv); 341*1da177e4SLinus Torvalds } 342