summaryrefslogtreecommitdiffstats
path: root/ncr-int.h
blob: fd508d0386f618f3b12231853af0628c40f6fa55 (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
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
#ifndef NCR_INT_H
# define NCR_INT_H

#include <linux/compat.h>
#include <linux/idr.h>
#include <linux/mutex.h>
#include "ncr.h"
#include <asm/atomic.h>
#include "cryptodev_int.h"
#include <ncr-pk.h>
#include <ncr-dh.h>

#define KEY_DATA_MAX_SIZE 3*1024
#define NCR_CIPHER_MAX_KEY_LEN 1024

#define err() printk(KERN_DEBUG"ncr: %s: %s: %d\n", __FILE__, __func__, __LINE__)

struct nlattr;
struct ncr_out;

// Not all known algorithms - only for quick internal identification.  Note
// that more than one struct algo_properties_st may share the same enum value!
typedef enum {
	NCR_ALG_NONE,
	NCR_ALG_NULL,

	NCR_ALG_3DES_CBC,
	NCR_ALG_3DES_ECB,

	NCR_ALG_AES_ECB,
	NCR_ALG_AES_CBC,
	NCR_ALG_AES_CTR,

	NCR_ALG_CAMELIA_ECB,
	NCR_ALG_CAMELIA_CBC,
	NCR_ALG_CAMELIA_CTR,

	NCR_ALG_MD5 = 200,
	NCR_ALG_SHA1,
	NCR_ALG_SHA2_224,
	NCR_ALG_SHA2_256,
	NCR_ALG_SHA2_384,
	NCR_ALG_SHA2_512,

	NCR_ALG_RSA = 600,
	NCR_ALG_DSA,
	NCR_ALG_DH,
} ncr_algorithm_t;

struct algo_oid_st {
	oid_st oid;
	int key_size;
};

struct algo_properties_st {
	ncr_algorithm_t algo;
	const char *kstr;
	size_t kstr_len;
	unsigned needs_iv:1;
	unsigned is_hmac:1;
	unsigned can_sign:1;
	unsigned can_digest:1;
	unsigned can_encrypt:1;
	unsigned can_kx:1;	/* key exchange */
	unsigned is_symmetric:1;
	unsigned is_pk:1;
	unsigned has_transparent_hash:1;
	int digest_size;
	/* NCR_KEY_TYPE_SECRET if for a secret key algorithm or MAC,
	 * NCR_KEY_TYPE_PUBLIC for a public key algorithm.
	 */
	ncr_key_type_t key_type;
	const struct algo_oid_st *oids;
};

struct key_item_st {
	/* This object is also not protected from concurrent access.
	 */
	ncr_key_type_t type;
	unsigned int flags;
	const struct algo_properties_st *algorithm;	/* non-NULL for public/private keys */
	uint8_t key_id[MAX_KEY_ID_SIZE];
	size_t key_id_size;

	union {
		struct {
			uint8_t data[NCR_CIPHER_MAX_KEY_LEN];
			size_t size;
		} secret;
		union {
			rsa_key rsa;
			dsa_key dsa;
			dh_key dh;
		} pk;
	} key;

	atomic_t refcnt;
	atomic_t writer;

	/* owner. The one charged with this */
	uid_t uid;
	pid_t pid;

	ncr_key_t desc;
};

/* all the data associated with the open descriptor
 * are here.
 */
struct ncr_lists {
	struct mutex key_idr_mutex;
	struct idr key_idr;

	/* sessions */
	struct mutex session_idr_mutex;
	struct idr session_idr;
};

void *ncr_init_lists(void);
void ncr_deinit_lists(struct ncr_lists *lst);

long ncr_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg);
long ncr_compat_ioctl(struct ncr_lists *lst, unsigned int cmd,
		      unsigned long arg);

/* key derivation */
int ncr_key_derive(struct ncr_lists *lst, const struct ncr_key_derive *data,
		   struct nlattr *tb[]);

void ncr_key_clear(struct key_item_st *item);
int ncr_key_update_flags(struct key_item_st *item, const struct nlattr *nla);

/* key handling */
int ncr_key_init(struct ncr_lists *lst);
int ncr_key_deinit(struct ncr_lists *lst, ncr_key_t desc);
int ncr_key_export(struct ncr_lists *lst, const struct ncr_key_export *data,
		   struct nlattr *tb[]);
int ncr_key_import(struct ncr_lists *lst, const struct ncr_key_import *data,
		   struct nlattr *tb[]);
void ncr_key_list_deinit(struct ncr_lists *lst);
int ncr_key_generate(struct ncr_lists *lst, const struct ncr_key_generate *gen,
		     struct nlattr *tb[]);
int ncr_key_get_info(struct ncr_lists *lst, struct ncr_out *out,
		     const struct ncr_key_get_info *info, struct nlattr *tb[]);

#ifdef CONFIG_CRYPTO_USERSPACE_ASYMMETRIC
int ncr_key_generate_pair(struct ncr_lists *lst,
			  const struct ncr_key_generate_pair *gen,
			  struct nlattr *tb[]);
#else
static inline int ncr_key_generate_pair(struct ncr_lists *lst,
					const struct ncr_key_generate_pair *gen,
					struct nlattr *tb[])
{
	return -EOPNOTSUPP;
}
#endif
int ncr_key_get_public(struct ncr_lists *lst, void __user * arg);

int ncr_key_item_get_read(struct key_item_st **st, struct ncr_lists *lst,
			  ncr_key_t desc);
/* get key item for writing */
int ncr_key_item_get_write(struct key_item_st **st,
			   struct ncr_lists *lst, ncr_key_t desc);
void _ncr_key_item_put(struct key_item_st *item);

typedef enum {
	LIMIT_TYPE_KEY,
	NUM_LIMIT_TYPES
} limits_type_t;

void ncr_limits_remove(uid_t uid, pid_t pid, limits_type_t type);
int ncr_limits_add_and_check(uid_t uid, pid_t pid, limits_type_t type);
void ncr_limits_init(void);
void ncr_limits_deinit(void);

#ifdef CONFIG_CRYPTO_USERSPACE_ASYMMETRIC
int ncr_key_wrap(struct ncr_lists *lst, const struct ncr_key_wrap *wrap,
		 struct nlattr *tb[]);
int ncr_key_unwrap(struct ncr_lists *lst, const struct ncr_key_unwrap *wrap,
		   struct nlattr *tb[]);
#else
static inline int ncr_key_wrap(struct ncr_lists *lst,
			       const struct ncr_key_wrap *wrap,
			       struct nlattr *tb[])
{
	return -EOPNOTSUPP;
}
static inline int ncr_key_unwrap(struct ncr_lists *lst,
				 const struct ncr_key_unwrap *wrap,
				 struct nlattr *tb[])
{
	return -EOPNOTSUPP;
}
#endif
int ncr_key_storage_wrap(struct ncr_lists *lst,
			 const struct ncr_key_storage_wrap *wrap,
			 struct nlattr *tb[]);
int ncr_key_storage_unwrap(struct ncr_lists *lst,
			   const struct ncr_key_storage_unwrap *wrap,
			   struct nlattr *tb[]);

/* sessions */
void ncr_sessions_list_deinit(struct ncr_lists *lst);

int ncr_session_init(struct ncr_lists *lists,
		     const struct ncr_session_init *session,
		     struct nlattr *tb[]);
int ncr_session_update(struct ncr_lists *lists,
		       const struct ncr_session_update *op, struct nlattr *tb[],
		       int compat);
int ncr_session_final(struct ncr_lists *lists,
		      const struct ncr_session_final *op, struct nlattr *tb[],
		      int compat);
int ncr_session_once(struct ncr_lists *lists,
		     const struct ncr_session_once *once, struct nlattr *tb[],
		     int compat);

/* master key */
extern struct key_item_st master_key;

void ncr_master_key_reset(void);

/* storage */
int key_from_storage_data(struct key_item_st *key, const void *data,
			  size_t data_size);
int key_to_storage_data(uint8_t ** data, size_t * data_size,
			const struct key_item_st *key);

/* misc helper macros */

const struct algo_properties_st *_ncr_algo_to_properties(ncr_algorithm_t algo);
const struct algo_properties_st *_ncr_nla_to_properties(const struct nlattr
							*nla);
int _ncr_key_get_sec_level(struct key_item_st *item);
const struct algo_properties_st *_ncr_oid_to_properties(const oid_st * oid);
const oid_st *_ncr_properties_to_oid(const struct algo_properties_st *prop,
				     int key_size);

/* CONFIG_COMPAT handling */

#ifdef CONFIG_COMPAT
struct compat_ncr_session_input_data {
	compat_uptr_t data;
	compat_size_t data_size;
};

struct compat_ncr_session_output_buffer {
	compat_uptr_t buffer;
	compat_size_t buffer_size;
	compat_uptr_t result_size_ptr;
};
#endif

int ncr_session_input_data_from_nla(struct ncr_session_input_data *dest,
				    const struct nlattr *nla, int compat);

int ncr_session_output_buffer_from_nla(struct ncr_session_output_buffer *dest,
				       const struct nlattr *nla, int compat);

int ncr_session_output_buffer_set_size(const struct ncr_session_output_buffer
				       *dest, size_t size, int compat);

#endif