1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | /* |
3 | * Copyright 2019 Google LLC |
4 | */ |
5 | |
6 | #ifndef _UFSHCD_CRYPTO_H |
7 | #define _UFSHCD_CRYPTO_H |
8 | |
9 | #include <scsi/scsi_cmnd.h> |
10 | #include <ufs/ufshcd.h> |
11 | #include "ufshcd-priv.h" |
12 | #include <ufs/ufshci.h> |
13 | |
14 | #ifdef CONFIG_SCSI_UFS_CRYPTO |
15 | |
16 | static inline void ufshcd_prepare_lrbp_crypto(struct request *rq, |
17 | struct ufshcd_lrb *lrbp) |
18 | { |
19 | if (!rq || !rq->crypt_keyslot) { |
20 | lrbp->crypto_key_slot = -1; |
21 | return; |
22 | } |
23 | |
24 | lrbp->crypto_key_slot = blk_crypto_keyslot_index(slot: rq->crypt_keyslot); |
25 | lrbp->data_unit_num = rq->crypt_ctx->bc_dun[0]; |
26 | } |
27 | |
28 | static inline void |
29 | ufshcd_prepare_req_desc_hdr_crypto(struct ufshcd_lrb *lrbp, |
30 | struct request_desc_header *h) |
31 | { |
32 | if (lrbp->crypto_key_slot < 0) |
33 | return; |
34 | h->enable_crypto = 1; |
35 | h->cci = lrbp->crypto_key_slot; |
36 | h->dunl = cpu_to_le32(lower_32_bits(lrbp->data_unit_num)); |
37 | h->dunu = cpu_to_le32(upper_32_bits(lrbp->data_unit_num)); |
38 | } |
39 | |
40 | static inline int ufshcd_crypto_fill_prdt(struct ufs_hba *hba, |
41 | struct ufshcd_lrb *lrbp) |
42 | { |
43 | struct scsi_cmnd *cmd = lrbp->cmd; |
44 | const struct bio_crypt_ctx *crypt_ctx = scsi_cmd_to_rq(scmd: cmd)->crypt_ctx; |
45 | |
46 | if (crypt_ctx && hba->vops && hba->vops->fill_crypto_prdt) |
47 | return hba->vops->fill_crypto_prdt(hba, crypt_ctx, |
48 | lrbp->ucd_prdt_ptr, |
49 | scsi_sg_count(cmd)); |
50 | return 0; |
51 | } |
52 | |
53 | static inline void ufshcd_crypto_clear_prdt(struct ufs_hba *hba, |
54 | struct ufshcd_lrb *lrbp) |
55 | { |
56 | if (!(hba->quirks & UFSHCD_QUIRK_KEYS_IN_PRDT)) |
57 | return; |
58 | |
59 | if (!(scsi_cmd_to_rq(scmd: lrbp->cmd)->crypt_ctx)) |
60 | return; |
61 | |
62 | /* Zeroize the PRDT because it can contain cryptographic keys. */ |
63 | memzero_explicit(s: lrbp->ucd_prdt_ptr, |
64 | count: ufshcd_sg_entry_size(hba) * scsi_sg_count(cmd: lrbp->cmd)); |
65 | } |
66 | |
67 | bool ufshcd_crypto_enable(struct ufs_hba *hba); |
68 | |
69 | int ufshcd_hba_init_crypto_capabilities(struct ufs_hba *hba); |
70 | |
71 | void ufshcd_init_crypto(struct ufs_hba *hba); |
72 | |
73 | void ufshcd_crypto_register(struct ufs_hba *hba, struct request_queue *q); |
74 | |
75 | #else /* CONFIG_SCSI_UFS_CRYPTO */ |
76 | |
77 | static inline void ufshcd_prepare_lrbp_crypto(struct request *rq, |
78 | struct ufshcd_lrb *lrbp) { } |
79 | |
80 | static inline void |
81 | ufshcd_prepare_req_desc_hdr_crypto(struct ufshcd_lrb *lrbp, |
82 | struct request_desc_header *h) { } |
83 | |
84 | static inline int ufshcd_crypto_fill_prdt(struct ufs_hba *hba, |
85 | struct ufshcd_lrb *lrbp) |
86 | { |
87 | return 0; |
88 | } |
89 | |
90 | static inline void ufshcd_crypto_clear_prdt(struct ufs_hba *hba, |
91 | struct ufshcd_lrb *lrbp) { } |
92 | |
93 | static inline bool ufshcd_crypto_enable(struct ufs_hba *hba) |
94 | { |
95 | return false; |
96 | } |
97 | |
98 | static inline int ufshcd_hba_init_crypto_capabilities(struct ufs_hba *hba) |
99 | { |
100 | return 0; |
101 | } |
102 | |
103 | static inline void ufshcd_init_crypto(struct ufs_hba *hba) { } |
104 | |
105 | static inline void ufshcd_crypto_register(struct ufs_hba *hba, |
106 | struct request_queue *q) { } |
107 | |
108 | #endif /* CONFIG_SCSI_UFS_CRYPTO */ |
109 | |
110 | #endif /* _UFSHCD_CRYPTO_H */ |
111 | |