summaryrefslogtreecommitdiffstats
path: root/src/include/gpxe/crypto.h
blob: fc1f50bc5ef2d23b6ac7d6ff320699699f22bcbf (plain) (blame)
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
#ifndef _GPXE_CRYPTO_H
#define _GPXE_CRYPTO_H

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

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

/** A cryptographic algorithm */
struct crypto_algorithm {
	/** Algorithm name */
	const char *name;
	/** Context size */
	size_t ctxsize;
	/** Block size */
	size_t blocksize;
	/** Final output size */
	size_t digestsize;
	/** Initialise algorithm
	 *
	 * @v ctx		Context
	 */
	void ( * init ) ( void *ctx );
	/** 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 );
	/** Encode data
	 *
	 * @v ctx		Context
	 * @v src		Data to encode
	 * @v dst		Encoded data, or NULL
	 * @v len		Length of data
	 * @ret rc		Return status code
	 *
	 * For a cipher algorithm, the enciphered data should be
	 * placed in @c dst.  For a digest algorithm, only the digest
	 * state should be updated, and @c dst will be NULL.
	 *
	 * @v len is guaranteed to be a multiple of @c blocksize.
	 */
	void ( * encode ) ( void *ctx, const void *src, void *dst,
			    size_t len );
	/** Decode data
	 *
	 * @v ctx		Context
	 * @v src		Data to decode
	 * @v dst		Decoded data
	 * @v len		Length of data
	 * @ret rc		Return status code
	 *
	 * @v len is guaranteed to be a multiple of @c blocksize.
	 */
	void ( * decode ) ( void *ctx, const void *src, void *dst,
			    size_t len );
	/** Finalise algorithm
	 *
	 * @v ctx		Context
	 * @v out		Algorithm final output
	 */
	void ( * final ) ( void *ctx, void *out );
};

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

static inline void digest_update ( struct crypto_algorithm *crypto,
				   void *ctx, const void *data, size_t len ) {
	crypto->encode ( ctx, data, NULL, len );
}

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

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

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

static inline int cipher_encrypt ( struct crypto_algorithm *crypto,
				   void *ctx, const void *src, void *dst,
				   size_t len ) {
	if ( ( len & ( crypto->blocksize - 1 ) ) ) {
		return -EINVAL;
	}
	crypto->encode ( ctx, src, dst, len );
	return 0;
}

static inline int cipher_decrypt ( struct crypto_algorithm *crypto,
				   void *ctx, const void *src, void *dst,
				   size_t len ) {
	if ( ( len & ( crypto->blocksize - 1 ) ) ) {
		return -EINVAL;
	}
	crypto->decode ( ctx, src, dst, len );
	return 0;
}

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

extern struct crypto_algorithm crypto_null;

#endif /* _GPXE_CRYPTO_H */