summaryrefslogtreecommitdiffstats
path: root/qemu/roms/ipxe/src/include/ipxe/crypto.h
blob: 3eda5ec6ee83e48f9697ba914be17c3896a11bdc (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
265
266
267
268
269
270
#ifndef _IPXE_CRYPTO_H
#define _IPXE_CRYPTO_H

/** @file
 *
 * Cryptographic API
 *
 */

FILE_LICENCE ( GPL2_OR_LATER );

#include <stdint.h>
#include <stddef.h>

/** A message digest algorithm */
struct digest_algorithm {
	/** Algorithm name */
	const char *name;
	/** Context size */
	size_t ctxsize;
	/** Block size */
	size_t blocksize;
	/** Digest size */
	size_t digestsize;
	/** Initialise digest
	 *
	 * @v ctx		Context
	 */
	void ( * init ) ( void *ctx );
	/** Update digest with new data
	 *
	 * @v ctx		Context
	 * @v src		Data to digest
	 * @v len		Length of data
	 *
	 * @v len is not necessarily a multiple of @c blocksize.
	 */
	void ( * update ) ( void *ctx, const void *src, size_t len );
	/** Finalise digest
	 *
	 * @v ctx		Context
	 * @v out		Buffer for digest output
	 */
	void ( * final ) ( void *ctx, void *out );
};

/** A cipher algorithm */
struct cipher_algorithm {
	/** Algorithm name */
	const char *name;
	/** Context size */
	size_t ctxsize;
	/** Block size */
	size_t blocksize;
	/** Set key
	 *
	 * @v ctx		Context
	 * @v key		Key
	 * @v keylen		Key length
	 * @ret rc		Return status code
	 */
	int ( * setkey ) ( void *ctx, const void *key, size_t keylen );
	/** Set initialisation vector
	 *
	 * @v ctx		Context
	 * @v iv		Initialisation vector
	 */
	void ( * setiv ) ( void *ctx, const void *iv );
	/** Encrypt data
	 *
	 * @v ctx		Context
	 * @v src		Data to encrypt
	 * @v dst		Buffer for encrypted data
	 * @v len		Length of data
	 *
	 * @v len is guaranteed to be a multiple of @c blocksize.
	 */
	void ( * encrypt ) ( void *ctx, const void *src, void *dst,
			     size_t len );
	/** Decrypt data
	 *
	 * @v ctx		Context
	 * @v src		Data to decrypt
	 * @v dst		Buffer for decrypted data
	 * @v len		Length of data
	 *
	 * @v len is guaranteed to be a multiple of @c blocksize.
	 */
	void ( * decrypt ) ( void *ctx, const void *src, void *dst,
			     size_t len );
};

/** A public key algorithm */
struct pubkey_algorithm {
	/** Algorithm name */
	const char *name;
	/** Context size */
	size_t ctxsize;
	/** Initialise algorithm
	 *
	 * @v ctx		Context
	 * @v key		Key
	 * @v key_len		Length of key
	 * @ret rc		Return status code
	 */
	int ( * init ) ( void *ctx, const void *key, size_t key_len );
	/** Calculate maximum output length
	 *
	 * @v ctx		Context
	 * @ret max_len		Maximum output length
	 */
	size_t ( * max_len ) ( void *ctx );
	/** Encrypt
	 *
	 * @v ctx		Context
	 * @v plaintext		Plaintext
	 * @v plaintext_len	Length of plaintext
	 * @v ciphertext	Ciphertext
	 * @ret ciphertext_len	Length of ciphertext, or negative error
	 */
	int ( * encrypt ) ( void *ctx, const void *data, size_t len,
			    void *out );
	/** Decrypt
	 *
	 * @v ctx		Context
	 * @v ciphertext	Ciphertext
	 * @v ciphertext_len	Ciphertext length
	 * @v plaintext		Plaintext
	 * @ret plaintext_len	Plaintext length, or negative error
	 */
	int ( * decrypt ) ( void *ctx, const void *data, size_t len,
			    void *out );
	/** Sign digest value
	 *
	 * @v ctx		Context
	 * @v digest		Digest algorithm
	 * @v value		Digest value
	 * @v signature		Signature
	 * @ret signature_len	Signature length, or negative error
	 */
	int ( * sign ) ( void *ctx, struct digest_algorithm *digest,
			 const void *value, void *signature );
	/** Verify signed digest value
	 *
	 * @v ctx		Context
	 * @v digest		Digest algorithm
	 * @v value		Digest value
	 * @v signature		Signature
	 * @v signature_len	Signature length
	 * @ret rc		Return status code
	 */
	int ( * verify ) ( void *ctx, struct digest_algorithm *digest,
			   const void *value, const void *signature,
			   size_t signature_len );
	/** Finalise algorithm
	 *
	 * @v ctx		Context
	 */
	void ( * final ) ( void *ctx );
	/** Check that public key matches private key
	 *
	 * @v private_key	Private key
	 * @v private_key_len	Private key length
	 * @v public_key	Public key
	 * @v public_key_len	Public key length
	 * @ret rc		Return status code
	 */
	int ( * match ) ( const void *private_key, size_t private_key_len,
			  const void *public_key, size_t public_key_len );
};

static inline void digest_init ( struct digest_algorithm *digest,
				 void *ctx ) {
	digest->init ( ctx );
}

static inline void digest_update ( struct digest_algorithm *digest,
				   void *ctx, const void *data, size_t len ) {
	digest->update ( ctx, data, len );
}

static inline void digest_final ( struct digest_algorithm *digest,
				  void *ctx, void *out ) {
	digest->final ( ctx, out );
}

static inline int cipher_setkey ( struct cipher_algorithm *cipher,
				  void *ctx, const void *key, size_t keylen ) {
	return cipher->setkey ( ctx, key, keylen );
}

static inline void cipher_setiv ( struct cipher_algorithm *cipher,
				  void *ctx, const void *iv ) {
	cipher->setiv ( ctx, iv );
}

static inline void cipher_encrypt ( struct cipher_algorithm *cipher,
				    void *ctx, const void *src, void *dst,
				    size_t len ) {
	cipher->encrypt ( ctx, src, dst, len );
}
#define cipher_encrypt( cipher, ctx, src, dst, len ) do {		\
	assert ( ( (len) & ( (cipher)->blocksize - 1 ) ) == 0 );	\
	cipher_encrypt ( (cipher), (ctx), (src), (dst), (len) );	\
	} while ( 0 )

static inline void cipher_decrypt ( struct cipher_algorithm *cipher,
				    void *ctx, const void *src, void *dst,
				    size_t len ) {
	cipher->decrypt ( ctx, src, dst, len );
}
#define cipher_decrypt( cipher, ctx, src, dst, len ) do {		\
	assert ( ( (len) & ( (cipher)->blocksize - 1 ) ) == 0 );	\
	cipher_decrypt ( (cipher), (ctx), (src), (dst), (len) );	\
	} while ( 0 )

static inline int is_stream_cipher ( struct cipher_algorithm *cipher ) {
	return ( cipher->blocksize == 1 );
}

static inline int pubkey_init ( struct pubkey_algorithm *pubkey, void *ctx,
				const void *key, size_t key_len ) {
	return pubkey->init ( ctx, key, key_len );
}

static inline size_t pubkey_max_len ( struct pubkey_algorithm *pubkey,
				      void *ctx ) {
	return pubkey->max_len ( ctx );
}

static inline int pubkey_encrypt ( struct pubkey_algorithm *pubkey, void *ctx,
				   const void *data, size_t len, void *out ) {
	return pubkey->encrypt ( ctx, data, len, out );
}

static inline int pubkey_decrypt ( struct pubkey_algorithm *pubkey, void *ctx,
				   const void *data, size_t len, void *out ) {
	return pubkey->decrypt ( ctx, data, len, out );
}

static inline int pubkey_sign ( struct pubkey_algorithm *pubkey, void *ctx,
				struct digest_algorithm *digest,
				const void *value, void *signature ) {
	return pubkey->sign ( ctx, digest, value, signature );
}

static inline int pubkey_verify ( struct pubkey_algorithm *pubkey, void *ctx,
				  struct digest_algorithm *digest,
				  const void *value, const void *signature,
				  size_t signature_len ) {
	return pubkey->verify ( ctx, digest, value, signature, signature_len );
}

static inline void pubkey_final ( struct pubkey_algorithm *pubkey, void *ctx ) {
	pubkey->final ( ctx );
}

static inline int pubkey_match ( struct pubkey_algorithm *pubkey,
				 const void *private_key,
				 size_t private_key_len, const void *public_key,
				 size_t public_key_len ) {
	return pubkey->match ( private_key, private_key_len, public_key,
			       public_key_len );
}

extern struct digest_algorithm digest_null;
extern struct cipher_algorithm cipher_null;
extern struct pubkey_algorithm pubkey_null;

#endif /* _IPXE_CRYPTO_H */