summaryrefslogtreecommitdiff
path: root/drivers/crypto/nx/nx.h
blob: de3ea8738146ba100faf1ede99f5058d6d6f5824 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195

#ifndef __NX_H__
#define __NX_H__

#define NX_NAME		"nx-crypto"
#define NX_STRING	"IBM Power7+ Nest Accelerator Crypto Driver"
#define NX_VERSION	"1.0"

static const char nx_driver_string[] = NX_STRING;
static const char nx_driver_version[] = NX_VERSION;

/* a scatterlist in the format PHYP is expecting */
struct nx_sg {
	u64 addr;
	u32 rsvd;
	u32 len;
} __attribute((packed));

#define NX_PAGE_SIZE		(4096)
#define NX_MAX_SG_ENTRIES	(NX_PAGE_SIZE/(sizeof(struct nx_sg)))

enum nx_status {
	NX_DISABLED,
	NX_WAITING,
	NX_OKAY
};

/* msc_triplet and max_sync_cop are used only to assist in parsing the
 * openFirmware property */
struct msc_triplet {
	u32 keybitlen;
	u32 databytelen;
	u32 sglen;
} __packed;

struct max_sync_cop {
	u32 fc;
	u32 mode;
	u32 triplets;
	struct msc_triplet trip[0];
} __packed;

struct alg_props {
	u32 databytelen;
	u32 sglen;
};

#define NX_OF_FLAG_MAXSGLEN_SET		(1)
#define NX_OF_FLAG_STATUS_SET		(2)
#define NX_OF_FLAG_MAXSYNCCOP_SET	(4)
#define NX_OF_FLAG_MASK_READY		(NX_OF_FLAG_MAXSGLEN_SET | \
					 NX_OF_FLAG_STATUS_SET |   \
					 NX_OF_FLAG_MAXSYNCCOP_SET)
struct nx_of {
	u32 flags;
	u32 max_sg_len;
	enum nx_status status;
	struct alg_props ap[NX_MAX_FC][NX_MAX_MODE][3];
};

struct nx_stats {
	atomic_t aes_ops;
	atomic64_t aes_bytes;
	atomic_t sha256_ops;
	atomic64_t sha256_bytes;
	atomic_t sha512_ops;
	atomic64_t sha512_bytes;

	atomic_t sync_ops;

	atomic_t errors;
	atomic_t last_error;
	atomic_t last_error_pid;
};

struct nx_debugfs {
	struct dentry *dfs_root;
	struct dentry *dfs_aes_ops, *dfs_aes_bytes;
	struct dentry *dfs_sha256_ops, *dfs_sha256_bytes;
	struct dentry *dfs_sha512_ops, *dfs_sha512_bytes;
	struct dentry *dfs_errors, *dfs_last_error, *dfs_last_error_pid;
};

struct nx_crypto_driver {
	struct nx_stats    stats;
	struct nx_of       of;
	struct vio_dev    *viodev;
	struct vio_driver  viodriver;
	struct nx_debugfs  dfs;
};

#define NX_GCM4106_NONCE_LEN		(4)
#define NX_GCM_CTR_OFFSET		(12)
struct nx_gcm_priv {
	u8 iv[16];
	u8 iauth_tag[16];
	u8 nonce[NX_GCM4106_NONCE_LEN];
};

#define NX_CCM_AES_KEY_LEN		(16)
#define NX_CCM4309_AES_KEY_LEN		(19)
#define NX_CCM4309_NONCE_LEN		(3)
struct nx_ccm_priv {
	u8 iv[16];
	u8 b0[16];
	u8 iauth_tag[16];
	u8 oauth_tag[16];
	u8 nonce[NX_CCM4309_NONCE_LEN];
};

struct nx_xcbc_priv {
	u8 key[16];
};

struct nx_ctr_priv {
	u8 iv[16];
};

struct nx_crypto_ctx {
	spinlock_t lock;	  /* synchronize access to the context */
	void *kmem;		  /* unaligned, kmalloc'd buffer */
	size_t kmem_len;	  /* length of kmem */
	struct nx_csbcpb *csbcpb; /* aligned page given to phyp @ hcall time */
	struct vio_pfo_op op;     /* operation struct with hcall parameters */
	struct nx_csbcpb *csbcpb_aead; /* secondary csbcpb used by AEAD algs */
	struct vio_pfo_op op_aead;/* operation struct for csbcpb_aead */

	struct nx_sg *in_sg;      /* aligned pointer into kmem to an sg list */
	struct nx_sg *out_sg;     /* aligned pointer into kmem to an sg list */

	struct alg_props *ap;	  /* pointer into props based on our key size */
	struct alg_props props[3];/* openFirmware properties for requests */
	struct nx_stats *stats;   /* pointer into an nx_crypto_driver for stats
				     reporting */

	union {
		struct nx_gcm_priv gcm;
		struct nx_ccm_priv ccm;
		struct nx_xcbc_priv xcbc;
		struct nx_ctr_priv ctr;
	} priv;
};

/* prototypes */
int nx_crypto_ctx_aes_ccm_init(struct crypto_tfm *tfm);
int nx_crypto_ctx_aes_gcm_init(struct crypto_aead *tfm);
int nx_crypto_ctx_aes_xcbc_init(struct crypto_tfm *tfm);
int nx_crypto_ctx_aes_ctr_init(struct crypto_tfm *tfm);
int nx_crypto_ctx_aes_cbc_init(struct crypto_tfm *tfm);
int nx_crypto_ctx_aes_ecb_init(struct crypto_tfm *tfm);
int nx_crypto_ctx_sha_init(struct crypto_tfm *tfm);
void nx_crypto_ctx_exit(struct crypto_tfm *tfm);
void nx_crypto_ctx_aead_exit(struct crypto_aead *tfm);
void nx_ctx_init(struct nx_crypto_ctx *nx_ctx, unsigned int function);
int nx_hcall_sync(struct nx_crypto_ctx *ctx, struct vio_pfo_op *op,
		  u32 may_sleep);
struct nx_sg *nx_build_sg_list(struct nx_sg *, u8 *, unsigned int *, u32);
int nx_build_sg_lists(struct nx_crypto_ctx *, struct blkcipher_desc *,
		      struct scatterlist *, struct scatterlist *, unsigned int *,
		      unsigned int, u8 *);
struct nx_sg *nx_walk_and_build(struct nx_sg *, unsigned int,
				struct scatterlist *, unsigned int,
				unsigned int *);

#ifdef CONFIG_DEBUG_FS
#define NX_DEBUGFS_INIT(drv)	nx_debugfs_init(drv)
#define NX_DEBUGFS_FINI(drv)	nx_debugfs_fini(drv)

int nx_debugfs_init(struct nx_crypto_driver *);
void nx_debugfs_fini(struct nx_crypto_driver *);
#else
#define NX_DEBUGFS_INIT(drv)	(0)
#define NX_DEBUGFS_FINI(drv)	(0)
#endif

#define NX_PAGE_NUM(x)		((u64)(x) & 0xfffffffffffff000ULL)

extern struct crypto_alg nx_cbc_aes_alg;
extern struct crypto_alg nx_ecb_aes_alg;
extern struct aead_alg nx_gcm_aes_alg;
extern struct aead_alg nx_gcm4106_aes_alg;
extern struct crypto_alg nx_ctr_aes_alg;
extern struct crypto_alg nx_ctr3686_aes_alg;
extern struct crypto_alg nx_ccm_aes_alg;
extern struct crypto_alg nx_ccm4309_aes_alg;
extern struct shash_alg nx_shash_aes_xcbc_alg;
extern struct shash_alg nx_shash_sha512_alg;
extern struct shash_alg nx_shash_sha256_alg;

extern struct nx_crypto_driver nx_driver;

#define SCATTERWALK_TO_SG	1
#define SCATTERWALK_FROM_SG	0

#endif