static int cbc_aes_crypt(struct blkcipher_desc *desc, long func, struct blkcipher_walk *walk) { struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm); int ret = blkcipher_walk_virt(desc, walk); unsigned int nbytes = walk->nbytes; struct { u8 iv[AES_BLOCK_SIZE]; u8 key[AES_MAX_KEY_SIZE]; } param; if (!nbytes) goto out; memcpy(param.iv, walk->iv, AES_BLOCK_SIZE); memcpy(param.key, sctx->key, sctx->key_len); do { /* only use complete blocks */ unsigned int n = nbytes & ~(AES_BLOCK_SIZE - 1); u8 *out = walk->dst.virt.addr; u8 *in = walk->src.virt.addr; ret = crypt_s390_kmc(func, ¶m, out, in, n); if (ret < 0 || ret != n) return -EIO; nbytes &= AES_BLOCK_SIZE - 1; ret = blkcipher_walk_done(desc, walk, nbytes); } while ((nbytes = walk->nbytes)); memcpy(walk->iv, param.iv, AES_BLOCK_SIZE); out: return ret; }
static int cbc_aes_crypt(struct blkcipher_desc *desc, long func, void *param, struct blkcipher_walk *walk) { int ret = blkcipher_walk_virt(desc, walk); unsigned int nbytes = walk->nbytes; if (!nbytes) goto out; memcpy(param, walk->iv, AES_BLOCK_SIZE); do { /* only use complete blocks */ unsigned int n = nbytes & ~(AES_BLOCK_SIZE - 1); u8 *out = walk->dst.virt.addr; u8 *in = walk->src.virt.addr; ret = crypt_s390_kmc(func, param, out, in, n); BUG_ON((ret < 0) || (ret != n)); nbytes &= AES_BLOCK_SIZE - 1; ret = blkcipher_walk_done(desc, walk, nbytes); } while ((nbytes = walk->nbytes)); memcpy(walk->iv, param, AES_BLOCK_SIZE); out: return ret; }
static unsigned int des_decrypt_cbc(const struct cipher_desc *desc, u8 *out, const u8 *in, unsigned int nbytes) { struct crypt_s390_des_ctx *sctx = crypto_tfm_ctx(desc->tfm); int ret; /* only use complete blocks */ nbytes &= ~(DES_BLOCK_SIZE - 1); memcpy(&sctx->iv, desc->info, DES_BLOCK_SIZE); ret = crypt_s390_kmc(KMC_DEA_DECRYPT, &sctx->iv, out, in, nbytes); BUG_ON((ret < 0) || (ret != nbytes)); return nbytes; }
static int init(void) { struct crypt_s390_query_status status = { .high = 0, .low = 0 }; printk(KERN_INFO "crypt_s390: querying available crypto functions\n"); crypt_s390_km(KM_QUERY, &status, NULL, NULL, 0); printk(KERN_INFO "KM:\t%016llx %016llx\n", (unsigned long long) status.high, (unsigned long long) status.low); status.high = status.low = 0; crypt_s390_kmc(KMC_QUERY, &status, NULL, NULL, 0); printk(KERN_INFO "KMC:\t%016llx %016llx\n", (unsigned long long) status.high, (unsigned long long) status.low); status.high = status.low = 0; crypt_s390_kimd(KIMD_QUERY, &status, NULL, 0); printk(KERN_INFO "KIMD:\t%016llx %016llx\n", (unsigned long long) status.high, (unsigned long long) status.low); status.high = status.low = 0; crypt_s390_klmd(KLMD_QUERY, &status, NULL, 0); printk(KERN_INFO "KLMD:\t%016llx %016llx\n", (unsigned long long) status.high, (unsigned long long) status.low); status.high = status.low = 0; crypt_s390_kmac(KMAC_QUERY, &status, NULL, 0); printk(KERN_INFO "KMAC:\t%016llx %016llx\n", (unsigned long long) status.high, (unsigned long long) status.low); query_available_functions(); return -ECANCELED; } static void __exit cleanup(void) { } module_init(init); module_exit(cleanup); MODULE_LICENSE("GPL");