1 /* 2 * Cryptographic API. 3 * 4 * s390 implementation of the AES Cipher Algorithm. 5 * 6 * s390 Version: 7 * Copyright (C) 2005 IBM Deutschland GmbH, IBM Corporation 8 * Author(s): Jan Glauber (jang@de.ibm.com) 9 * 10 * Derived from "crypto/aes.c" 11 * 12 * This program is free software; you can redistribute it and/or modify it 13 * under the terms of the GNU General Public License as published by the Free 14 * Software Foundation; either version 2 of the License, or (at your option) 15 * any later version. 16 * 17 */ 18 19 #include <crypto/algapi.h> 20 #include <linux/module.h> 21 #include <linux/init.h> 22 #include "crypt_s390.h" 23 24 #define AES_MIN_KEY_SIZE 16 25 #define AES_MAX_KEY_SIZE 32 26 27 /* data block size for all key lengths */ 28 #define AES_BLOCK_SIZE 16 29 30 int has_aes_128 = 0; 31 int has_aes_192 = 0; 32 int has_aes_256 = 0; 33 34 struct s390_aes_ctx { 35 u8 iv[AES_BLOCK_SIZE]; 36 u8 key[AES_MAX_KEY_SIZE]; 37 long enc; 38 long dec; 39 int key_len; 40 }; 41 42 static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, 43 unsigned int key_len) 44 { 45 struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm); 46 u32 *flags = &tfm->crt_flags; 47 48 switch (key_len) { 49 case 16: 50 if (!has_aes_128) 51 goto fail; 52 break; 53 case 24: 54 if (!has_aes_192) 55 goto fail; 56 57 break; 58 case 32: 59 if (!has_aes_256) 60 goto fail; 61 break; 62 default: 63 /* invalid key length */ 64 goto fail; 65 break; 66 } 67 68 sctx->key_len = key_len; 69 memcpy(sctx->key, in_key, key_len); 70 return 0; 71 fail: 72 *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; 73 return -EINVAL; 74 } 75 76 static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) 77 { 78 const struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm); 79 80 switch (sctx->key_len) { 81 case 16: 82 crypt_s390_km(KM_AES_128_ENCRYPT, &sctx->key, out, in, 83 AES_BLOCK_SIZE); 84 break; 85 case 24: 86 crypt_s390_km(KM_AES_192_ENCRYPT, &sctx->key, out, in, 87 AES_BLOCK_SIZE); 88 break; 89 case 32: 90 crypt_s390_km(KM_AES_256_ENCRYPT, &sctx->key, out, in, 91 AES_BLOCK_SIZE); 92 break; 93 } 94 } 95 96 static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) 97 { 98 const struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm); 99 100 switch (sctx->key_len) { 101 case 16: 102 crypt_s390_km(KM_AES_128_DECRYPT, &sctx->key, out, in, 103 AES_BLOCK_SIZE); 104 break; 105 case 24: 106 crypt_s390_km(KM_AES_192_DECRYPT, &sctx->key, out, in, 107 AES_BLOCK_SIZE); 108 break; 109 case 32: 110 crypt_s390_km(KM_AES_256_DECRYPT, &sctx->key, out, in, 111 AES_BLOCK_SIZE); 112 break; 113 } 114 } 115 116 117 static struct crypto_alg aes_alg = { 118 .cra_name = "aes", 119 .cra_driver_name = "aes-s390", 120 .cra_priority = CRYPT_S390_PRIORITY, 121 .cra_flags = CRYPTO_ALG_TYPE_CIPHER, 122 .cra_blocksize = AES_BLOCK_SIZE, 123 .cra_ctxsize = sizeof(struct s390_aes_ctx), 124 .cra_module = THIS_MODULE, 125 .cra_list = LIST_HEAD_INIT(aes_alg.cra_list), 126 .cra_u = { 127 .cipher = { 128 .cia_min_keysize = AES_MIN_KEY_SIZE, 129 .cia_max_keysize = AES_MAX_KEY_SIZE, 130 .cia_setkey = aes_set_key, 131 .cia_encrypt = aes_encrypt, 132 .cia_decrypt = aes_decrypt, 133 } 134 } 135 }; 136 137 static int ecb_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, 138 unsigned int key_len) 139 { 140 struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm); 141 142 switch (key_len) { 143 case 16: 144 sctx->enc = KM_AES_128_ENCRYPT; 145 sctx->dec = KM_AES_128_DECRYPT; 146 break; 147 case 24: 148 sctx->enc = KM_AES_192_ENCRYPT; 149 sctx->dec = KM_AES_192_DECRYPT; 150 break; 151 case 32: 152 sctx->enc = KM_AES_256_ENCRYPT; 153 sctx->dec = KM_AES_256_DECRYPT; 154 break; 155 } 156 157 return aes_set_key(tfm, in_key, key_len); 158 } 159 160 static int ecb_aes_crypt(struct blkcipher_desc *desc, long func, void *param, 161 struct blkcipher_walk *walk) 162 { 163 int ret = blkcipher_walk_virt(desc, walk); 164 unsigned int nbytes; 165 166 while ((nbytes = walk->nbytes)) { 167 /* only use complete blocks */ 168 unsigned int n = nbytes & ~(AES_BLOCK_SIZE - 1); 169 u8 *out = walk->dst.virt.addr; 170 u8 *in = walk->src.virt.addr; 171 172 ret = crypt_s390_km(func, param, out, in, n); 173 BUG_ON((ret < 0) || (ret != n)); 174 175 nbytes &= AES_BLOCK_SIZE - 1; 176 ret = blkcipher_walk_done(desc, walk, nbytes); 177 } 178 179 return ret; 180 } 181 182 static int ecb_aes_encrypt(struct blkcipher_desc *desc, 183 struct scatterlist *dst, struct scatterlist *src, 184 unsigned int nbytes) 185 { 186 struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm); 187 struct blkcipher_walk walk; 188 189 blkcipher_walk_init(&walk, dst, src, nbytes); 190 return ecb_aes_crypt(desc, sctx->enc, sctx->key, &walk); 191 } 192 193 static int ecb_aes_decrypt(struct blkcipher_desc *desc, 194 struct scatterlist *dst, struct scatterlist *src, 195 unsigned int nbytes) 196 { 197 struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm); 198 struct blkcipher_walk walk; 199 200 blkcipher_walk_init(&walk, dst, src, nbytes); 201 return ecb_aes_crypt(desc, sctx->dec, sctx->key, &walk); 202 } 203 204 static struct crypto_alg ecb_aes_alg = { 205 .cra_name = "ecb(aes)", 206 .cra_driver_name = "ecb-aes-s390", 207 .cra_priority = CRYPT_S390_COMPOSITE_PRIORITY, 208 .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, 209 .cra_blocksize = AES_BLOCK_SIZE, 210 .cra_ctxsize = sizeof(struct s390_aes_ctx), 211 .cra_type = &crypto_blkcipher_type, 212 .cra_module = THIS_MODULE, 213 .cra_list = LIST_HEAD_INIT(ecb_aes_alg.cra_list), 214 .cra_u = { 215 .blkcipher = { 216 .min_keysize = AES_MIN_KEY_SIZE, 217 .max_keysize = AES_MAX_KEY_SIZE, 218 .setkey = ecb_aes_set_key, 219 .encrypt = ecb_aes_encrypt, 220 .decrypt = ecb_aes_decrypt, 221 } 222 } 223 }; 224 225 static int cbc_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, 226 unsigned int key_len) 227 { 228 struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm); 229 230 switch (key_len) { 231 case 16: 232 sctx->enc = KMC_AES_128_ENCRYPT; 233 sctx->dec = KMC_AES_128_DECRYPT; 234 break; 235 case 24: 236 sctx->enc = KMC_AES_192_ENCRYPT; 237 sctx->dec = KMC_AES_192_DECRYPT; 238 break; 239 case 32: 240 sctx->enc = KMC_AES_256_ENCRYPT; 241 sctx->dec = KMC_AES_256_DECRYPT; 242 break; 243 } 244 245 return aes_set_key(tfm, in_key, key_len); 246 } 247 248 static int cbc_aes_crypt(struct blkcipher_desc *desc, long func, void *param, 249 struct blkcipher_walk *walk) 250 { 251 int ret = blkcipher_walk_virt(desc, walk); 252 unsigned int nbytes = walk->nbytes; 253 254 if (!nbytes) 255 goto out; 256 257 memcpy(param, walk->iv, AES_BLOCK_SIZE); 258 do { 259 /* only use complete blocks */ 260 unsigned int n = nbytes & ~(AES_BLOCK_SIZE - 1); 261 u8 *out = walk->dst.virt.addr; 262 u8 *in = walk->src.virt.addr; 263 264 ret = crypt_s390_kmc(func, param, out, in, n); 265 BUG_ON((ret < 0) || (ret != n)); 266 267 nbytes &= AES_BLOCK_SIZE - 1; 268 ret = blkcipher_walk_done(desc, walk, nbytes); 269 } while ((nbytes = walk->nbytes)); 270 memcpy(walk->iv, param, AES_BLOCK_SIZE); 271 272 out: 273 return ret; 274 } 275 276 static int cbc_aes_encrypt(struct blkcipher_desc *desc, 277 struct scatterlist *dst, struct scatterlist *src, 278 unsigned int nbytes) 279 { 280 struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm); 281 struct blkcipher_walk walk; 282 283 blkcipher_walk_init(&walk, dst, src, nbytes); 284 return cbc_aes_crypt(desc, sctx->enc, sctx->iv, &walk); 285 } 286 287 static int cbc_aes_decrypt(struct blkcipher_desc *desc, 288 struct scatterlist *dst, struct scatterlist *src, 289 unsigned int nbytes) 290 { 291 struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm); 292 struct blkcipher_walk walk; 293 294 blkcipher_walk_init(&walk, dst, src, nbytes); 295 return cbc_aes_crypt(desc, sctx->dec, sctx->iv, &walk); 296 } 297 298 static struct crypto_alg cbc_aes_alg = { 299 .cra_name = "cbc(aes)", 300 .cra_driver_name = "cbc-aes-s390", 301 .cra_priority = CRYPT_S390_COMPOSITE_PRIORITY, 302 .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, 303 .cra_blocksize = AES_BLOCK_SIZE, 304 .cra_ctxsize = sizeof(struct s390_aes_ctx), 305 .cra_type = &crypto_blkcipher_type, 306 .cra_module = THIS_MODULE, 307 .cra_list = LIST_HEAD_INIT(cbc_aes_alg.cra_list), 308 .cra_u = { 309 .blkcipher = { 310 .min_keysize = AES_MIN_KEY_SIZE, 311 .max_keysize = AES_MAX_KEY_SIZE, 312 .ivsize = AES_BLOCK_SIZE, 313 .setkey = cbc_aes_set_key, 314 .encrypt = cbc_aes_encrypt, 315 .decrypt = cbc_aes_decrypt, 316 } 317 } 318 }; 319 320 static int __init aes_init(void) 321 { 322 int ret; 323 324 if (crypt_s390_func_available(KM_AES_128_ENCRYPT)) 325 has_aes_128 = 1; 326 if (crypt_s390_func_available(KM_AES_192_ENCRYPT)) 327 has_aes_192 = 1; 328 if (crypt_s390_func_available(KM_AES_256_ENCRYPT)) 329 has_aes_256 = 1; 330 331 if (!has_aes_128 && !has_aes_192 && !has_aes_256) 332 return -ENOSYS; 333 334 ret = crypto_register_alg(&aes_alg); 335 if (ret != 0) { 336 printk(KERN_INFO "crypt_s390: aes-s390 couldn't be loaded.\n"); 337 goto aes_err; 338 } 339 340 ret = crypto_register_alg(&ecb_aes_alg); 341 if (ret != 0) { 342 printk(KERN_INFO 343 "crypt_s390: ecb-aes-s390 couldn't be loaded.\n"); 344 goto ecb_aes_err; 345 } 346 347 ret = crypto_register_alg(&cbc_aes_alg); 348 if (ret != 0) { 349 printk(KERN_INFO 350 "crypt_s390: cbc-aes-s390 couldn't be loaded.\n"); 351 goto cbc_aes_err; 352 } 353 354 out: 355 return ret; 356 357 cbc_aes_err: 358 crypto_unregister_alg(&ecb_aes_alg); 359 ecb_aes_err: 360 crypto_unregister_alg(&aes_alg); 361 aes_err: 362 goto out; 363 } 364 365 static void __exit aes_fini(void) 366 { 367 crypto_unregister_alg(&cbc_aes_alg); 368 crypto_unregister_alg(&ecb_aes_alg); 369 crypto_unregister_alg(&aes_alg); 370 } 371 372 module_init(aes_init); 373 module_exit(aes_fini); 374 375 MODULE_ALIAS("aes"); 376 377 MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm"); 378 MODULE_LICENSE("GPL"); 379 380