static int ccp_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key, unsigned int key_len) { struct ccp_ctx *ctx = crypto_tfm_ctx(crypto_ablkcipher_tfm(tfm)); struct ccp_crypto_ablkcipher_alg *alg = ccp_crypto_ablkcipher_alg(crypto_ablkcipher_tfm(tfm)); switch (key_len) { case AES_KEYSIZE_128: ctx->u.aes.type = CCP_AES_TYPE_128; break; case AES_KEYSIZE_192: ctx->u.aes.type = CCP_AES_TYPE_192; break; case AES_KEYSIZE_256: ctx->u.aes.type = CCP_AES_TYPE_256; break; default: crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); return -EINVAL; } ctx->u.aes.mode = alg->mode; ctx->u.aes.key_len = key_len; memcpy(ctx->u.aes.key, key, key_len); sg_init_one(&ctx->u.aes.key_sg, ctx->u.aes.key, key_len); return 0; }
/* async interface */ static int dcp_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key, unsigned int len) { struct dcp_op *ctx = crypto_ablkcipher_ctx(tfm); unsigned int ret = 0; ctx->keylen = len; ctx->flags = 0; if (len == AES_KEYSIZE_128) { if (memcmp(ctx->key, key, AES_KEYSIZE_128)) { memcpy(ctx->key, key, len); ctx->flags |= DCP_NEW_KEY; } return 0; } ctx->fallback->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK; ctx->fallback->base.crt_flags |= (tfm->base.crt_flags & CRYPTO_TFM_REQ_MASK); ret = crypto_ablkcipher_setkey(ctx->fallback, key, len); if (ret) { struct crypto_tfm *tfm_aux = crypto_ablkcipher_tfm(tfm); tfm_aux->crt_flags &= ~CRYPTO_TFM_RES_MASK; tfm_aux->crt_flags |= (ctx->fallback->base.crt_flags & CRYPTO_TFM_RES_MASK); } return ret; }
static int qce_ablkcipher_crypt(struct ablkcipher_request *req, int encrypt) { struct crypto_tfm *tfm = crypto_ablkcipher_tfm(crypto_ablkcipher_reqtfm(req)); struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm); struct qce_cipher_reqctx *rctx = ablkcipher_request_ctx(req); struct qce_alg_template *tmpl = to_cipher_tmpl(tfm); int ret; rctx->flags = tmpl->alg_flags; rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT; if (IS_AES(rctx->flags) && ctx->enc_keylen != AES_KEYSIZE_128 && ctx->enc_keylen != AES_KEYSIZE_256) { SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback); skcipher_request_set_sync_tfm(subreq, ctx->fallback); skcipher_request_set_callback(subreq, req->base.flags, NULL, NULL); skcipher_request_set_crypt(subreq, req->src, req->dst, req->nbytes, req->info); ret = encrypt ? crypto_skcipher_encrypt(subreq) : crypto_skcipher_decrypt(subreq); skcipher_request_zero(subreq); return ret; } return tmpl->qce->async_req_enqueue(tmpl->qce, &req->base); }
/** * AES Functions */ static int crypto4xx_setkey_aes(struct crypto_ablkcipher *cipher, const u8 *key, unsigned int keylen, unsigned char cm, u8 fb) { struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher); struct crypto4xx_ctx *ctx = crypto_tfm_ctx(tfm); struct dynamic_sa_ctl *sa; int rc; if (keylen != AES_KEYSIZE_256 && keylen != AES_KEYSIZE_192 && keylen != AES_KEYSIZE_128) { crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN); return -EINVAL; } /* Create SA */ if (ctx->sa_in || ctx->sa_out) crypto4xx_free_sa(ctx); rc = crypto4xx_alloc_sa(ctx, SA_AES128_LEN + (keylen-16) / 4); if (rc) return rc; /* Setup SA */ sa = ctx->sa_in; set_dynamic_sa_command_0(sa, SA_NOT_SAVE_HASH, SA_NOT_SAVE_IV, SA_LOAD_HASH_FROM_SA, SA_LOAD_IV_FROM_STATE, SA_NO_HEADER_PROC, SA_HASH_ALG_NULL, SA_CIPHER_ALG_AES, SA_PAD_TYPE_ZERO, SA_OP_GROUP_BASIC, SA_OPCODE_DECRYPT, DIR_INBOUND); set_dynamic_sa_command_1(sa, cm, SA_HASH_MODE_HASH, fb, SA_EXTENDED_SN_OFF, SA_SEQ_MASK_OFF, SA_MC_ENABLE, SA_NOT_COPY_PAD, SA_NOT_COPY_PAYLOAD, SA_NOT_COPY_HDR); crypto4xx_memcpy_to_le32(get_dynamic_sa_key_field(sa), key, keylen); sa->sa_contents.w = SA_AES_CONTENTS | (keylen << 2); sa->sa_command_1.bf.key_len = keylen >> 3; memcpy(ctx->sa_out, ctx->sa_in, ctx->sa_len * 4); sa = ctx->sa_out; sa->sa_command_0.bf.dir = DIR_OUTBOUND; return 0; }
static int ccp_aes_rfc3686_setkey(struct crypto_ablkcipher *tfm, const u8 *key, unsigned int key_len) { struct ccp_ctx *ctx = crypto_tfm_ctx(crypto_ablkcipher_tfm(tfm)); if (key_len < CTR_RFC3686_NONCE_SIZE) return -EINVAL; key_len -= CTR_RFC3686_NONCE_SIZE; memcpy(ctx->u.aes.nonce, key + key_len, CTR_RFC3686_NONCE_SIZE); return ccp_aes_setkey(tfm, key, key_len); }
static int s5p_aes_setkey(struct crypto_ablkcipher *cipher, const uint8_t *key, unsigned int keylen) { struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher); struct s5p_aes_ctx *ctx = crypto_tfm_ctx(tfm); if (keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_192 && keylen != AES_KEYSIZE_256) return -EINVAL; memcpy(ctx->aes_key, key, keylen); ctx->keylen = keylen; return 0; }
static int dcp_aes_cbc_decrypt(struct ablkcipher_request *req) { struct crypto_tfm *tfm = crypto_ablkcipher_tfm(crypto_ablkcipher_reqtfm(req)); struct dcp_op *ctx = crypto_ablkcipher_ctx( crypto_ablkcipher_reqtfm(req)); if (unlikely(ctx->keylen != AES_KEYSIZE_128)) { int err = 0; ablkcipher_request_set_tfm(req, ctx->fallback); err = crypto_ablkcipher_decrypt(req); ablkcipher_request_set_tfm(req, __crypto_ablkcipher_cast(tfm)); return err; } return dcp_aes_cbc_crypt(req, DCP_AES | DCP_DEC | DCP_CBC); }
static int sahara_aes_cbc_decrypt(struct ablkcipher_request *req) { struct crypto_tfm *tfm = crypto_ablkcipher_tfm(crypto_ablkcipher_reqtfm(req)); struct sahara_ctx *ctx = crypto_ablkcipher_ctx( crypto_ablkcipher_reqtfm(req)); int err; if (unlikely(ctx->keylen != AES_KEYSIZE_128)) { ablkcipher_request_set_tfm(req, ctx->fallback); err = crypto_ablkcipher_decrypt(req); ablkcipher_request_set_tfm(req, __crypto_ablkcipher_cast(tfm)); return err; } return sahara_aes_crypt(req, FLAGS_CBC); }
int crypto4xx_setkey_rfc3686(struct crypto_ablkcipher *cipher, const u8 *key, unsigned int keylen) { struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher); struct crypto4xx_ctx *ctx = crypto_tfm_ctx(tfm); int rc; rc = crypto4xx_setkey_aes(cipher, key, keylen - CTR_RFC3686_NONCE_SIZE, CRYPTO_MODE_CTR, CRYPTO_FEEDBACK_MODE_NO_FB); if (rc) return rc; ctx->iv_nonce = cpu_to_le32p((u32 *)&key[keylen - CTR_RFC3686_NONCE_SIZE]); return 0; }
static int cryptd_blkcipher_enqueue(struct ablkcipher_request *req, crypto_completion_t complete) { struct cryptd_blkcipher_request_ctx *rctx = ablkcipher_request_ctx(req); struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); struct cryptd_state *state = cryptd_get_state(crypto_ablkcipher_tfm(tfm)); int err; rctx->complete = req->base.complete; req->base.complete = complete; spin_lock_bh(&state->lock); err = ablkcipher_enqueue_request(&state->queue, req); spin_unlock_bh(&state->lock); wake_up_process(state->task); return err; }
static int mv_setkey_aes(struct crypto_ablkcipher *cipher, const u8 *key, unsigned int len) { struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher); struct mv_ctx *ctx = crypto_tfm_ctx(tfm); switch (len) { case AES_KEYSIZE_128: case AES_KEYSIZE_192: case AES_KEYSIZE_256: break; default: crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN); return -EINVAL; } ctx->key_len = len; ctx->need_calc_aes_dkey = 1; memcpy(ctx->aes_enc_key, key, AES_KEY_LEN); return 0; }
static int qce_ablkcipher_setkey(struct crypto_ablkcipher *ablk, const u8 *key, unsigned int keylen) { struct crypto_tfm *tfm = crypto_ablkcipher_tfm(ablk); struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm); unsigned long flags = to_cipher_tmpl(tfm)->alg_flags; int ret; if (!key || !keylen) return -EINVAL; if (IS_AES(flags)) { switch (keylen) { case AES_KEYSIZE_128: case AES_KEYSIZE_256: break; default: goto fallback; } } else if (IS_DES(flags)) { u32 tmp[DES_EXPKEY_WORDS]; ret = des_ekey(tmp, key); if (!ret && crypto_ablkcipher_get_flags(ablk) & CRYPTO_TFM_REQ_WEAK_KEY) goto weakkey; } ctx->enc_keylen = keylen; memcpy(ctx->enc_key, key, keylen); return 0; fallback: ret = crypto_sync_skcipher_setkey(ctx->fallback, key, keylen); if (!ret) ctx->enc_keylen = keylen; return ret; weakkey: crypto_ablkcipher_set_flags(ablk, CRYPTO_TFM_RES_WEAK_KEY); return -EINVAL; }
static int qce_ablkcipher_crypt(struct ablkcipher_request *req, int encrypt) { struct crypto_tfm *tfm = crypto_ablkcipher_tfm(crypto_ablkcipher_reqtfm(req)); struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm); struct qce_cipher_reqctx *rctx = ablkcipher_request_ctx(req); struct qce_alg_template *tmpl = to_cipher_tmpl(tfm); int ret; rctx->flags = tmpl->alg_flags; rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT; if (IS_AES(rctx->flags) && ctx->enc_keylen != AES_KEYSIZE_128 && ctx->enc_keylen != AES_KEYSIZE_256) { ablkcipher_request_set_tfm(req, ctx->fallback); ret = encrypt ? crypto_ablkcipher_encrypt(req) : crypto_ablkcipher_decrypt(req); ablkcipher_request_set_tfm(req, __crypto_ablkcipher_cast(tfm)); return ret; } return tmpl->qce->async_req_enqueue(tmpl->qce, &req->base); }
static int sahara_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key, unsigned int keylen) { struct sahara_ctx *ctx = crypto_ablkcipher_ctx(tfm); int ret; ctx->keylen = keylen; /* SAHARA only supports 128bit keys */ if (keylen == AES_KEYSIZE_128) { memcpy(ctx->key, key, keylen); ctx->flags |= FLAGS_NEW_KEY; return 0; } if (keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_192 && keylen != AES_KEYSIZE_256) return -EINVAL; /* * The requested key size is not supported by HW, do a fallback. */ ctx->fallback->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK; ctx->fallback->base.crt_flags |= (tfm->base.crt_flags & CRYPTO_TFM_REQ_MASK); ret = crypto_ablkcipher_setkey(ctx->fallback, key, keylen); if (ret) { struct crypto_tfm *tfm_aux = crypto_ablkcipher_tfm(tfm); tfm_aux->crt_flags &= ~CRYPTO_TFM_RES_MASK; tfm_aux->crt_flags |= (ctx->fallback->base.crt_flags & CRYPTO_TFM_RES_MASK); } return ret; }
int get_crypt_info(struct inode *inode) { struct fscrypt_info *crypt_info; u8 full_key_descriptor[FS_KEY_DESC_PREFIX_SIZE + (FS_KEY_DESCRIPTOR_SIZE * 2) + 1]; struct key *keyring_key = NULL; struct fscrypt_key *master_key; struct fscrypt_context ctx; struct user_key_payload *ukp; struct crypto_ablkcipher *ctfm; const char *cipher_str; u8 raw_key[FS_MAX_KEY_SIZE]; u8 mode; int res; res = fscrypt_initialize(); if (res) return res; if (!inode->i_sb->s_cop->get_context) return -EOPNOTSUPP; retry: crypt_info = ACCESS_ONCE(inode->i_crypt_info); if (crypt_info) { if (!crypt_info->ci_keyring_key || key_validate(crypt_info->ci_keyring_key) == 0) return 0; fscrypt_put_encryption_info(inode, crypt_info); goto retry; } res = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx)); if (res < 0) { if (!fscrypt_dummy_context_enabled(inode)) return res; ctx.contents_encryption_mode = FS_ENCRYPTION_MODE_AES_256_XTS; ctx.filenames_encryption_mode = FS_ENCRYPTION_MODE_AES_256_CTS; ctx.flags = 0; } else if (res != sizeof(ctx)) { return -EINVAL; } res = 0; crypt_info = kmem_cache_alloc(fscrypt_info_cachep, GFP_NOFS); if (!crypt_info) return -ENOMEM; crypt_info->ci_flags = ctx.flags; crypt_info->ci_data_mode = ctx.contents_encryption_mode; crypt_info->ci_filename_mode = ctx.filenames_encryption_mode; crypt_info->ci_ctfm = NULL; crypt_info->ci_keyring_key = NULL; memcpy(crypt_info->ci_master_key, ctx.master_key_descriptor, sizeof(crypt_info->ci_master_key)); if (S_ISREG(inode->i_mode)) mode = crypt_info->ci_data_mode; else if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) mode = crypt_info->ci_filename_mode; else BUG(); switch (mode) { case FS_ENCRYPTION_MODE_AES_256_XTS: cipher_str = "xts(aes)"; break; case FS_ENCRYPTION_MODE_AES_256_CTS: cipher_str = "cts(cbc(aes))"; break; default: printk_once(KERN_WARNING "%s: unsupported key mode %d (ino %u)\n", __func__, mode, (unsigned) inode->i_ino); res = -ENOKEY; goto out; } if (fscrypt_dummy_context_enabled(inode)) { memset(raw_key, 0x42, FS_AES_256_XTS_KEY_SIZE); goto got_key; } memcpy(full_key_descriptor, FS_KEY_DESC_PREFIX, FS_KEY_DESC_PREFIX_SIZE); sprintf(full_key_descriptor + FS_KEY_DESC_PREFIX_SIZE, "%*phN", FS_KEY_DESCRIPTOR_SIZE, ctx.master_key_descriptor); full_key_descriptor[FS_KEY_DESC_PREFIX_SIZE + (2 * FS_KEY_DESCRIPTOR_SIZE)] = '\0'; keyring_key = request_key(&key_type_logon, full_key_descriptor, NULL); if (IS_ERR(keyring_key)) { res = PTR_ERR(keyring_key); keyring_key = NULL; goto out; } crypt_info->ci_keyring_key = keyring_key; if (keyring_key->type != &key_type_logon) { printk_once(KERN_WARNING "%s: key type must be logon\n", __func__); res = -ENOKEY; goto out; } down_read(&keyring_key->sem); ukp = ((struct user_key_payload *)keyring_key->payload.data); if (ukp->datalen != sizeof(struct fscrypt_key)) { res = -EINVAL; up_read(&keyring_key->sem); goto out; } master_key = (struct fscrypt_key *)ukp->data; BUILD_BUG_ON(FS_AES_128_ECB_KEY_SIZE != FS_KEY_DERIVATION_NONCE_SIZE); if (master_key->size != FS_AES_256_XTS_KEY_SIZE) { printk_once(KERN_WARNING "%s: key size incorrect: %d\n", __func__, master_key->size); res = -ENOKEY; up_read(&keyring_key->sem); goto out; } res = derive_key_aes(ctx.nonce, master_key->raw, raw_key); up_read(&keyring_key->sem); if (res) goto out; got_key: ctfm = crypto_alloc_ablkcipher(cipher_str, 0, 0); if (!ctfm || IS_ERR(ctfm)) { res = ctfm ? PTR_ERR(ctfm) : -ENOMEM; printk(KERN_DEBUG "%s: error %d (inode %u) allocating crypto tfm\n", __func__, res, (unsigned) inode->i_ino); goto out; } crypt_info->ci_ctfm = ctfm; crypto_ablkcipher_clear_flags(ctfm, ~0); crypto_tfm_set_flags(crypto_ablkcipher_tfm(ctfm), CRYPTO_TFM_REQ_WEAK_KEY); res = crypto_ablkcipher_setkey(ctfm, raw_key, fscrypt_key_size(mode)); if (res) goto out; memzero_explicit(raw_key, sizeof(raw_key)); if (cmpxchg(&inode->i_crypt_info, NULL, crypt_info) != NULL) { put_crypt_info(crypt_info); goto retry; } return 0; out: if (res == -ENOKEY) res = 0; put_crypt_info(crypt_info); memzero_explicit(raw_key, sizeof(raw_key)); return res; }
static int async_setkey(struct crypto_ablkcipher *tfm, const u8 *key, unsigned int keylen) { return setkey(crypto_ablkcipher_tfm(tfm), key, keylen); }
int _ext4_get_encryption_info(struct inode *inode) { struct ext4_inode_info *ei = EXT4_I(inode); struct ext4_crypt_info *crypt_info; char full_key_descriptor[EXT4_KEY_DESC_PREFIX_SIZE + (EXT4_KEY_DESCRIPTOR_SIZE * 2) + 1]; struct key *keyring_key = NULL; struct ext4_encryption_key *master_key; struct ext4_encryption_context ctx; struct user_key_payload *ukp; struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); struct crypto_ablkcipher *ctfm; const char *cipher_str; char raw_key[EXT4_MAX_KEY_SIZE]; char mode; int res; if (!ext4_read_workqueue) { res = ext4_init_crypto(); if (res) return res; } retry: crypt_info = ACCESS_ONCE(ei->i_crypt_info); if (crypt_info) { if (!crypt_info->ci_keyring_key || key_validate(crypt_info->ci_keyring_key) == 0) return 0; ext4_free_encryption_info(inode, crypt_info); goto retry; } res = ext4_xattr_get(inode, EXT4_XATTR_INDEX_ENCRYPTION, EXT4_XATTR_NAME_ENCRYPTION_CONTEXT, &ctx, sizeof(ctx)); if (res < 0) { if (!DUMMY_ENCRYPTION_ENABLED(sbi)) return res; ctx.contents_encryption_mode = EXT4_ENCRYPTION_MODE_AES_256_XTS; ctx.filenames_encryption_mode = EXT4_ENCRYPTION_MODE_AES_256_CTS; ctx.flags = 0; } else if (res != sizeof(ctx)) return -EINVAL; res = 0; crypt_info = kmem_cache_alloc(ext4_crypt_info_cachep, GFP_KERNEL); if (!crypt_info) return -ENOMEM; crypt_info->ci_flags = ctx.flags; crypt_info->ci_data_mode = ctx.contents_encryption_mode; crypt_info->ci_filename_mode = ctx.filenames_encryption_mode; crypt_info->ci_ctfm = NULL; crypt_info->ci_keyring_key = NULL; memcpy(crypt_info->ci_master_key, ctx.master_key_descriptor, sizeof(crypt_info->ci_master_key)); if (S_ISREG(inode->i_mode)) mode = crypt_info->ci_data_mode; else if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) mode = crypt_info->ci_filename_mode; else BUG(); switch (mode) { case EXT4_ENCRYPTION_MODE_AES_256_XTS: cipher_str = "xts(aes)"; break; case EXT4_ENCRYPTION_MODE_AES_256_CTS: cipher_str = "cts(cbc(aes))"; break; default: printk_once(KERN_WARNING "ext4: unsupported key mode %d (ino %u)\n", mode, (unsigned) inode->i_ino); res = -ENOKEY; goto out; } if (DUMMY_ENCRYPTION_ENABLED(sbi)) { memset(raw_key, 0x42, EXT4_AES_256_XTS_KEY_SIZE); goto got_key; } memcpy(full_key_descriptor, EXT4_KEY_DESC_PREFIX, EXT4_KEY_DESC_PREFIX_SIZE); sprintf(full_key_descriptor + EXT4_KEY_DESC_PREFIX_SIZE, "%*phN", EXT4_KEY_DESCRIPTOR_SIZE, ctx.master_key_descriptor); full_key_descriptor[EXT4_KEY_DESC_PREFIX_SIZE + (2 * EXT4_KEY_DESCRIPTOR_SIZE)] = '\0'; keyring_key = request_key(&key_type_logon, full_key_descriptor, NULL); if (IS_ERR(keyring_key)) { res = PTR_ERR(keyring_key); keyring_key = NULL; goto out; } crypt_info->ci_keyring_key = keyring_key; if (keyring_key->type != &key_type_logon) { printk_once(KERN_WARNING "ext4: key type must be logon\n"); res = -ENOKEY; goto out; } ukp = ((struct user_key_payload *)keyring_key->payload.data); if (ukp->datalen != sizeof(struct ext4_encryption_key)) { res = -EINVAL; goto out; } master_key = (struct ext4_encryption_key *)ukp->data; BUILD_BUG_ON(EXT4_AES_128_ECB_KEY_SIZE != EXT4_KEY_DERIVATION_NONCE_SIZE); if (master_key->size != EXT4_AES_256_XTS_KEY_SIZE) { printk_once(KERN_WARNING "ext4: key size incorrect: %d\n", master_key->size); res = -ENOKEY; goto out; } res = ext4_derive_key_aes(ctx.nonce, master_key->raw, raw_key); got_key: ctfm = crypto_alloc_ablkcipher(cipher_str, 0, 0); if (!ctfm || IS_ERR(ctfm)) { res = ctfm ? PTR_ERR(ctfm) : -ENOMEM; printk(KERN_DEBUG "%s: error %d (inode %u) allocating crypto tfm\n", __func__, res, (unsigned) inode->i_ino); goto out; } crypt_info->ci_ctfm = ctfm; crypto_ablkcipher_clear_flags(ctfm, ~0); crypto_tfm_set_flags(crypto_ablkcipher_tfm(ctfm), CRYPTO_TFM_REQ_WEAK_KEY); res = crypto_ablkcipher_setkey(ctfm, raw_key, ext4_encryption_key_size(mode)); if (res) goto out; memzero_explicit(raw_key, sizeof(raw_key)); if (cmpxchg(&ei->i_crypt_info, NULL, crypt_info) != NULL) { ext4_free_crypt_info(crypt_info); goto retry; } return 0; out: if (res == -ENOKEY) res = 0; ext4_free_crypt_info(crypt_info); memzero_explicit(raw_key, sizeof(raw_key)); return res; }
static int cc_cipher_setkey(struct crypto_ablkcipher *atfm, const u8 *key, unsigned int keylen) { struct crypto_tfm *tfm = crypto_ablkcipher_tfm(atfm); struct cc_cipher_ctx *ctx_p = crypto_tfm_ctx(tfm); struct device *dev = drvdata_to_dev(ctx_p->drvdata); u32 tmp[DES_EXPKEY_WORDS]; unsigned int max_key_buf_size = get_max_keysize(tfm); dev_dbg(dev, "Setting key in context @%p for %s. keylen=%u\n", ctx_p, crypto_tfm_alg_name(tfm), keylen); dump_byte_array("key", (u8 *)key, keylen); /* STAT_PHASE_0: Init and sanity checks */ if (validate_keys_sizes(ctx_p, keylen)) { dev_err(dev, "Unsupported key size %d.\n", keylen); crypto_tfm_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); return -EINVAL; } if (cc_is_hw_key(tfm)) { /* setting HW key slots */ struct arm_hw_key_info *hki = (struct arm_hw_key_info *)key; if (ctx_p->flow_mode != S_DIN_to_AES) { dev_err(dev, "HW key not supported for non-AES flows\n"); return -EINVAL; } ctx_p->hw.key1_slot = hw_key_to_cc_hw_key(hki->hw_key1); if (ctx_p->hw.key1_slot == END_OF_KEYS) { dev_err(dev, "Unsupported hw key1 number (%d)\n", hki->hw_key1); return -EINVAL; } if (ctx_p->cipher_mode == DRV_CIPHER_XTS || ctx_p->cipher_mode == DRV_CIPHER_ESSIV || ctx_p->cipher_mode == DRV_CIPHER_BITLOCKER) { if (hki->hw_key1 == hki->hw_key2) { dev_err(dev, "Illegal hw key numbers (%d,%d)\n", hki->hw_key1, hki->hw_key2); return -EINVAL; } ctx_p->hw.key2_slot = hw_key_to_cc_hw_key(hki->hw_key2); if (ctx_p->hw.key2_slot == END_OF_KEYS) { dev_err(dev, "Unsupported hw key2 number (%d)\n", hki->hw_key2); return -EINVAL; } } ctx_p->keylen = keylen; dev_dbg(dev, "cc_is_hw_key ret 0"); return 0; } // verify weak keys if (ctx_p->flow_mode == S_DIN_to_DES) { if (!des_ekey(tmp, key) && (crypto_tfm_get_flags(tfm) & CRYPTO_TFM_REQ_WEAK_KEY)) { tfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY; dev_dbg(dev, "weak DES key"); return -EINVAL; } } if (ctx_p->cipher_mode == DRV_CIPHER_XTS && xts_check_key(tfm, key, keylen)) { dev_dbg(dev, "weak XTS key"); return -EINVAL; } if (ctx_p->flow_mode == S_DIN_to_DES && keylen == DES3_EDE_KEY_SIZE && cc_verify_3des_keys(key, keylen)) { dev_dbg(dev, "weak 3DES key"); return -EINVAL; } /* STAT_PHASE_1: Copy key to ctx */ dma_sync_single_for_cpu(dev, ctx_p->user.key_dma_addr, max_key_buf_size, DMA_TO_DEVICE); memcpy(ctx_p->user.key, key, keylen); if (keylen == 24) memset(ctx_p->user.key + 24, 0, CC_AES_KEY_SIZE_MAX - 24); if (ctx_p->cipher_mode == DRV_CIPHER_ESSIV) { /* sha256 for key2 - use sw implementation */ int key_len = keylen >> 1; int err; SHASH_DESC_ON_STACK(desc, ctx_p->shash_tfm); desc->tfm = ctx_p->shash_tfm; err = crypto_shash_digest(desc, ctx_p->user.key, key_len, ctx_p->user.key + key_len); if (err) { dev_err(dev, "Failed to hash ESSIV key.\n"); return err; } }
int _f2fs_get_encryption_info(struct inode *inode) { struct f2fs_inode_info *fi = F2FS_I(inode); struct f2fs_crypt_info *crypt_info; char full_key_descriptor[F2FS_KEY_DESC_PREFIX_SIZE + (F2FS_KEY_DESCRIPTOR_SIZE * 2) + 1]; struct key *keyring_key = NULL; struct f2fs_encryption_key *master_key; struct f2fs_encryption_context ctx; const struct user_key_payload *ukp; struct crypto_ablkcipher *ctfm; const char *cipher_str; char raw_key[F2FS_MAX_KEY_SIZE]; char mode; int res; res = f2fs_crypto_initialize(); if (res) return res; retry: crypt_info = ACCESS_ONCE(fi->i_crypt_info); if (crypt_info) { if (!crypt_info->ci_keyring_key || key_validate(crypt_info->ci_keyring_key) == 0) return 0; f2fs_free_encryption_info(inode, crypt_info); goto retry; } res = f2fs_getxattr(inode, F2FS_XATTR_INDEX_ENCRYPTION, F2FS_XATTR_NAME_ENCRYPTION_CONTEXT, &ctx, sizeof(ctx), NULL); if (res < 0) return res; else if (res != sizeof(ctx)) return -EINVAL; res = 0; crypt_info = kmem_cache_alloc(f2fs_crypt_info_cachep, GFP_NOFS); if (!crypt_info) return -ENOMEM; crypt_info->ci_flags = ctx.flags; crypt_info->ci_data_mode = ctx.contents_encryption_mode; crypt_info->ci_filename_mode = ctx.filenames_encryption_mode; crypt_info->ci_ctfm = NULL; crypt_info->ci_keyring_key = NULL; memcpy(crypt_info->ci_master_key, ctx.master_key_descriptor, sizeof(crypt_info->ci_master_key)); if (S_ISREG(inode->i_mode)) mode = crypt_info->ci_data_mode; else if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) mode = crypt_info->ci_filename_mode; else BUG(); switch (mode) { case F2FS_ENCRYPTION_MODE_AES_256_XTS: cipher_str = "xts(aes)"; break; case F2FS_ENCRYPTION_MODE_AES_256_CTS: cipher_str = "cts(cbc(aes))"; break; default: printk_once(KERN_WARNING "f2fs: unsupported key mode %d (ino %u)\n", mode, (unsigned) inode->i_ino); res = -ENOKEY; goto out; } memcpy(full_key_descriptor, F2FS_KEY_DESC_PREFIX, F2FS_KEY_DESC_PREFIX_SIZE); sprintf(full_key_descriptor + F2FS_KEY_DESC_PREFIX_SIZE, "%*phN", F2FS_KEY_DESCRIPTOR_SIZE, ctx.master_key_descriptor); full_key_descriptor[F2FS_KEY_DESC_PREFIX_SIZE + (2 * F2FS_KEY_DESCRIPTOR_SIZE)] = '\0'; keyring_key = request_key(&key_type_logon, full_key_descriptor, NULL); if (IS_ERR(keyring_key)) { res = PTR_ERR(keyring_key); keyring_key = NULL; goto out; } crypt_info->ci_keyring_key = keyring_key; BUG_ON(keyring_key->type != &key_type_logon); ukp = user_key_payload(keyring_key); if (ukp->datalen != sizeof(struct f2fs_encryption_key)) { res = -EINVAL; goto out; } master_key = (struct f2fs_encryption_key *)ukp->data; BUILD_BUG_ON(F2FS_AES_128_ECB_KEY_SIZE != F2FS_KEY_DERIVATION_NONCE_SIZE); BUG_ON(master_key->size != F2FS_AES_256_XTS_KEY_SIZE); res = f2fs_derive_key_aes(ctx.nonce, master_key->raw, raw_key); if (res) goto out; ctfm = crypto_alloc_ablkcipher(cipher_str, 0, 0); if (!ctfm || IS_ERR(ctfm)) { res = ctfm ? PTR_ERR(ctfm) : -ENOMEM; printk(KERN_DEBUG "%s: error %d (inode %u) allocating crypto tfm\n", __func__, res, (unsigned) inode->i_ino); goto out; } crypt_info->ci_ctfm = ctfm; crypto_ablkcipher_clear_flags(ctfm, ~0); crypto_tfm_set_flags(crypto_ablkcipher_tfm(ctfm), CRYPTO_TFM_REQ_WEAK_KEY); res = crypto_ablkcipher_setkey(ctfm, raw_key, f2fs_encryption_key_size(mode)); if (res) goto out; memzero_explicit(raw_key, sizeof(raw_key)); if (cmpxchg(&fi->i_crypt_info, NULL, crypt_info) != NULL) { f2fs_free_crypt_info(crypt_info); goto retry; } return 0; out: if (res == -ENOKEY && !S_ISREG(inode->i_mode)) res = 0; f2fs_free_crypt_info(crypt_info); memzero_explicit(raw_key, sizeof(raw_key)); return res; }