Kaynağa Gözat

[crypto] Add our own general-purpose cipher-block chaining routines

tags/v0.9.7
Michael Brown 15 yıl önce
ebeveyn
işleme
e950dc04ba

+ 4
- 6
src/crypto/axtls/aes.c Dosyayı Görüntüle

@@ -152,10 +152,6 @@ static const unsigned char Rcon[30]=
152 152
 	0xb3,0x7d,0xfa,0xef,0xc5,0x91,
153 153
 };
154 154
 
155
-/* ----- static functions ----- */
156
-static void AES_encrypt(const AES_CTX *ctx, uint32_t *data);
157
-static void AES_decrypt(const AES_CTX *ctx, uint32_t *data);
158
-
159 155
 /* Perform doubling in Galois Field GF(2^8) using the irreducible polynomial
160 156
    x^8+x^4+x^3+x+1 */
161 157
 static unsigned char AES_xtime(uint32_t x)
@@ -257,6 +253,7 @@ void AES_convert_key(AES_CTX *ctx)
257 253
     }
258 254
 }
259 255
 
256
+#if 0
260 257
 /**
261 258
  * Encrypt a byte sequence (with a block size 16) using the AES cipher.
262 259
  */
@@ -358,11 +355,12 @@ void AES_cbc_decrypt(AES_CTX *ctx, const uint8_t *msg, uint8_t *out, int length)
358 355
     l2n(xor2, iv);
359 356
     l2n(xor3, iv);
360 357
 }
358
+#endif
361 359
 
362 360
 /**
363 361
  * Encrypt a single block (16 bytes) of data
364 362
  */
365
-static void AES_encrypt(const AES_CTX *ctx, uint32_t *data)
363
+void AES_encrypt(const AES_CTX *ctx, uint32_t *data)
366 364
 {
367 365
     /* To make this code smaller, generate the sbox entries on the fly.
368 366
      * This will have a really heavy effect upon performance.
@@ -418,7 +416,7 @@ static void AES_encrypt(const AES_CTX *ctx, uint32_t *data)
418 416
 /**
419 417
  * Decrypt a single block (16 bytes) of data
420 418
  */
421
-static void AES_decrypt(const AES_CTX *ctx, uint32_t *data)
419
+void AES_decrypt(const AES_CTX *ctx, uint32_t *data)
422 420
 { 
423 421
     uint32_t tmp[4];
424 422
     uint32_t xt0,xt1,xt2,xt3,xt4,xt5,xt6;

+ 2
- 0
src/crypto/axtls/crypto.h Dosyayı Görüntüle

@@ -55,6 +55,8 @@ void AES_cbc_encrypt(AES_CTX *ctx, const uint8_t *msg,
55 55
         uint8_t *out, int length);
56 56
 void AES_cbc_decrypt(AES_CTX *ks, const uint8_t *in, uint8_t *out, int length);
57 57
 void AES_convert_key(AES_CTX *ctx);
58
+void AES_encrypt(const AES_CTX *ctx, uint32_t *data);
59
+void AES_decrypt(const AES_CTX *ctx, uint32_t *data);
58 60
 
59 61
 /**************************************************************************
60 62
  * RC4 declarations 

+ 208
- 23
src/crypto/axtls_aes.c Dosyayı Görüntüle

@@ -1,17 +1,65 @@
1
-#include "crypto/axtls/crypto.h"
1
+/*
2
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
2 19
 #include <string.h>
3 20
 #include <errno.h>
21
+#include <byteswap.h>
4 22
 #include <gpxe/crypto.h>
23
+#include <gpxe/cbc.h>
5 24
 #include <gpxe/aes.h>
25
+#include "crypto/axtls/crypto.h"
6 26
 
7
-struct aes_cbc_context {
8
-	AES_CTX ctx;
27
+/** @file
28
+ *
29
+ * AES algorithm
30
+ *
31
+ */
32
+
33
+/** Basic AES blocksize */
34
+#define AES_BLOCKSIZE 16
35
+
36
+/****************************************************************************
37
+ *
38
+ * Basic AES algorithm (independent of mode of operation)
39
+ *
40
+ ****************************************************************************
41
+ */
42
+
43
+/** AES context */
44
+struct aes_context {
45
+	/** AES context for AXTLS */
46
+	AES_CTX axtls_ctx;
47
+	/** Cipher is being used for decrypting */
9 48
 	int decrypting;
10 49
 };
11 50
 
12
-static int aes_cbc_setkey ( void *ctx, const void *key, size_t keylen ) {
13
-	struct aes_cbc_context *aesctx = ctx;
51
+/**
52
+ * Set key
53
+ *
54
+ * @v ctx		Context
55
+ * @v key		Key
56
+ * @v keylen		Key length
57
+ * @ret rc		Return status code
58
+ */
59
+static int aes_setkey ( void *ctx, const void *key, size_t keylen ) {
60
+	struct aes_context *aes_ctx = ctx;
14 61
 	AES_MODE mode;
62
+	void *iv;
15 63
 
16 64
 	switch ( keylen ) {
17 65
 	case ( 128 / 8 ):
@@ -24,45 +72,182 @@ static int aes_cbc_setkey ( void *ctx, const void *key, size_t keylen ) {
24 72
 		return -EINVAL;
25 73
 	}
26 74
 
27
-	AES_set_key ( &aesctx->ctx, key, aesctx->ctx.iv, mode );
75
+	/* IV is not a relevant concept at this stage; use a dummy
76
+	 * value that will have no side-effects.
77
+	 */
78
+	iv = &aes_ctx->axtls_ctx.iv;
79
+
80
+	AES_set_key ( &aes_ctx->axtls_ctx, key, iv, mode );
28 81
 
29
-	aesctx->decrypting = 0;
82
+	aes_ctx->decrypting = 0;
30 83
 
31 84
 	return 0;
32 85
 }
33 86
 
34
-static void aes_cbc_setiv ( void *ctx, const void *iv ) {
35
-	struct aes_cbc_context *aesctx = ctx;
87
+/**
88
+ * Set initialisation vector
89
+ *
90
+ * @v ctx		Context
91
+ * @v iv		Initialisation vector
92
+ */
93
+static void aes_setiv ( void *ctx __unused, const void *iv __unused ) {
94
+	/* Nothing to do */
95
+}
36 96
 
37
-	memcpy ( aesctx->ctx.iv, iv, sizeof ( aesctx->ctx.iv ) );
97
+/**
98
+ * Call AXTLS' AES_encrypt() or AES_decrypt() functions
99
+ *
100
+ * @v axtls_ctx		AXTLS AES context
101
+ * @v src		Data to process
102
+ * @v dst		Buffer for output
103
+ * @v func		AXTLS AES function to call
104
+ */
105
+static void aes_call_axtls ( AES_CTX *axtls_ctx, const void *src, void *dst,
106
+			     void ( * func ) ( const AES_CTX *axtls_ctx,
107
+					       uint32_t *data ) ){
108
+	const uint32_t *srcl = src;
109
+	uint32_t *dstl = dst;
110
+	unsigned int i;
111
+
112
+	/* AXTLS' AES_encrypt() and AES_decrypt() functions both
113
+	 * expect to deal with an array of four dwords in host-endian
114
+	 * order.
115
+	 */
116
+	for ( i = 0 ; i < 4 ; i++ )
117
+		dstl[i] = ntohl ( srcl[i] );
118
+	func ( axtls_ctx, dstl );
119
+	for ( i = 0 ; i < 4 ; i++ )
120
+		dstl[i] = htonl ( dstl[i] );
38 121
 }
39 122
 
40
-static void aes_cbc_encrypt ( void *ctx, const void *data, void *dst,
41
-			      size_t len ) {
42
-	struct aes_cbc_context *aesctx = ctx;
123
+/**
124
+ * Encrypt data
125
+ *
126
+ * @v ctx		Context
127
+ * @v src		Data to encrypt
128
+ * @v dst		Buffer for encrypted data
129
+ * @v len		Length of data
130
+ */
131
+static void aes_encrypt ( void *ctx, const void *src, void *dst,
132
+			  size_t len ) {
133
+	struct aes_context *aes_ctx = ctx;
43 134
 
44
-	if ( aesctx->decrypting )
135
+	assert ( len == AES_BLOCKSIZE );
136
+	if ( aes_ctx->decrypting )
45 137
 		assert ( 0 );
138
+	aes_call_axtls ( &aes_ctx->axtls_ctx, src, dst, AES_encrypt );
139
+}
140
+
141
+/**
142
+ * Decrypt data
143
+ *
144
+ * @v ctx		Context
145
+ * @v src		Data to decrypt
146
+ * @v dst		Buffer for decrypted data
147
+ * @v len		Length of data
148
+ */
149
+static void aes_decrypt ( void *ctx, const void *src, void *dst,
150
+			  size_t len ) {
151
+	struct aes_context *aes_ctx = ctx;
152
+
153
+	assert ( len == AES_BLOCKSIZE );
154
+	if ( ! aes_ctx->decrypting ) {
155
+		AES_convert_key ( &aes_ctx->axtls_ctx );
156
+		aes_ctx->decrypting = 1;
157
+	}
158
+	aes_call_axtls ( &aes_ctx->axtls_ctx, src, dst, AES_decrypt );
159
+}
160
+
161
+/** Basic AES algorithm */
162
+static struct cipher_algorithm aes_algorithm = {
163
+	.name = "aes",
164
+	.ctxsize = sizeof ( struct aes_context ),
165
+	.blocksize = AES_BLOCKSIZE,
166
+	.setkey = aes_setkey,
167
+	.setiv = aes_setiv,
168
+	.encrypt = aes_encrypt,
169
+	.decrypt = aes_decrypt,
170
+};
171
+
172
+/****************************************************************************
173
+ *
174
+ * AES with cipher-block chaining (CBC)
175
+ *
176
+ ****************************************************************************
177
+ */
178
+
179
+/** AES with CBC context */
180
+struct aes_cbc_context {
181
+	/** AES context */
182
+	struct aes_context aes_ctx;
183
+	/** CBC context */
184
+	uint8_t cbc_ctx[AES_BLOCKSIZE];
185
+};
186
+
187
+/**
188
+ * Set key
189
+ *
190
+ * @v ctx		Context
191
+ * @v key		Key
192
+ * @v keylen		Key length
193
+ * @ret rc		Return status code
194
+ */
195
+static int aes_cbc_setkey ( void *ctx, const void *key, size_t keylen ) {
196
+	struct aes_cbc_context *aes_cbc_ctx = ctx;
46 197
 
47
-	AES_cbc_encrypt ( &aesctx->ctx, data, dst, len );
198
+	return cbc_setkey ( ctx, key, keylen, &aes_algorithm,
199
+			    &aes_cbc_ctx->cbc_ctx );
48 200
 }
49 201
 
50
-static void aes_cbc_decrypt ( void *ctx, const void *data, void *dst,
202
+/**
203
+ * Set initialisation vector
204
+ *
205
+ * @v ctx		Context
206
+ * @v iv		Initialisation vector
207
+ */
208
+static void aes_cbc_setiv ( void *ctx, const void *iv ) {
209
+	struct aes_cbc_context *aes_cbc_ctx = ctx;
210
+
211
+	cbc_setiv ( ctx, iv, &aes_algorithm, &aes_cbc_ctx->cbc_ctx );
212
+}
213
+
214
+/**
215
+ * Encrypt data
216
+ *
217
+ * @v ctx		Context
218
+ * @v src		Data to encrypt
219
+ * @v dst		Buffer for encrypted data
220
+ * @v len		Length of data
221
+ */
222
+static void aes_cbc_encrypt ( void *ctx, const void *src, void *dst,
51 223
 			      size_t len ) {
52
-	struct aes_cbc_context *aesctx = ctx;
224
+	struct aes_cbc_context *aes_cbc_ctx = ctx;
53 225
 
54
-	if ( ! aesctx->decrypting ) {
55
-		AES_convert_key ( &aesctx->ctx );
56
-		aesctx->decrypting = 1;
57
-	}
226
+	cbc_encrypt ( &aes_cbc_ctx->aes_ctx, src, dst, len,
227
+		      &aes_algorithm, &aes_cbc_ctx->cbc_ctx );
228
+}
229
+
230
+/**
231
+ * Decrypt data
232
+ *
233
+ * @v ctx		Context
234
+ * @v src		Data to decrypt
235
+ * @v dst		Buffer for decrypted data
236
+ * @v len		Length of data
237
+ */
238
+static void aes_cbc_decrypt ( void *ctx, const void *src, void *dst,
239
+			      size_t len ) {
240
+	struct aes_cbc_context *aes_cbc_ctx = ctx;
58 241
 
59
-	AES_cbc_decrypt ( &aesctx->ctx, data, dst, len );
242
+	cbc_decrypt ( &aes_cbc_ctx->aes_ctx, src, dst, len,
243
+		      &aes_algorithm, &aes_cbc_ctx->cbc_ctx );
60 244
 }
61 245
 
246
+/* AES with cipher-block chaining */
62 247
 struct cipher_algorithm aes_cbc_algorithm = {
63 248
 	.name		= "aes_cbc",
64 249
 	.ctxsize	= sizeof ( struct aes_cbc_context ),
65
-	.blocksize	= 16,
250
+	.blocksize	= AES_BLOCKSIZE,
66 251
 	.setkey		= aes_cbc_setkey,
67 252
 	.setiv		= aes_cbc_setiv,
68 253
 	.encrypt	= aes_cbc_encrypt,

+ 99
- 0
src/crypto/cbc.c Dosyayı Görüntüle

@@ -0,0 +1,99 @@
1
+/*
2
+ * Copyright (C) 2009 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
19
+#include <string.h>
20
+#include <assert.h>
21
+#include <gpxe/crypto.h>
22
+#include <gpxe/cbc.h>
23
+
24
+/** @file
25
+ *
26
+ * Cipher-block chaining
27
+ *
28
+ */
29
+
30
+/**
31
+ * XOR data blocks
32
+ *
33
+ * @v src		Input data
34
+ * @v dst		Second input data and output data buffer
35
+ * @v len		Length of data
36
+ */
37
+static void cbc_xor ( const void *src, void *dst, size_t len ) {
38
+	const uint32_t *srcl = src;
39
+	uint32_t *dstl = dst;
40
+	unsigned int i;
41
+
42
+	/* Assume that block sizes will always be dword-aligned, for speed */
43
+	assert ( ( len % sizeof ( *srcl ) ) == 0 );
44
+
45
+	for ( i = 0 ; i < ( len / sizeof ( *srcl ) ) ; i++ )
46
+		dstl[i] ^= srcl[i];
47
+}
48
+
49
+/**
50
+ * Encrypt data
51
+ *
52
+ * @v ctx		Context
53
+ * @v src		Data to encrypt
54
+ * @v dst		Buffer for encrypted data
55
+ * @v len		Length of data
56
+ * @v cipher		Underlying cipher algorithm
57
+ * @v cbc_ctx		CBC context
58
+ */
59
+void cbc_encrypt ( void *ctx, const void *src, void *dst, size_t len,
60
+		   struct cipher_algorithm *cipher, void *cbc_ctx ) {
61
+	size_t blocksize = cipher->blocksize;
62
+
63
+	assert ( ( len % blocksize ) == 0 );
64
+
65
+	while ( len ) {
66
+		cbc_xor ( src, cbc_ctx, blocksize );
67
+		cipher_encrypt ( cipher, ctx, cbc_ctx, dst, blocksize );
68
+		memcpy ( cbc_ctx, dst, blocksize );
69
+		dst += blocksize;
70
+		src += blocksize;
71
+		len -= blocksize;
72
+	}
73
+}
74
+
75
+/**
76
+ * Decrypt data
77
+ *
78
+ * @v ctx		Context
79
+ * @v src		Data to decrypt
80
+ * @v dst		Buffer for decrypted data
81
+ * @v len		Length of data
82
+ * @v cipher		Underlying cipher algorithm
83
+ * @v cbc_ctx		CBC context
84
+ */
85
+void cbc_decrypt ( void *ctx, const void *src, void *dst, size_t len,
86
+		   struct cipher_algorithm *cipher, void *cbc_ctx ) {
87
+	size_t blocksize = cipher->blocksize;
88
+
89
+	assert ( ( len % blocksize ) == 0 );
90
+
91
+	while ( len ) {
92
+		cipher_decrypt ( cipher, ctx, src, dst, blocksize );
93
+		cbc_xor ( cbc_ctx, dst, blocksize );
94
+		memcpy ( cbc_ctx, src, blocksize );
95
+		dst += blocksize;
96
+		src += blocksize;
97
+		len -= blocksize;
98
+	}
99
+}

+ 50
- 0
src/include/gpxe/cbc.h Dosyayı Görüntüle

@@ -0,0 +1,50 @@
1
+#ifndef _GPXE_CBC_H
2
+#define _GPXE_CBC_H
3
+
4
+/** @file
5
+ *
6
+ * Cipher-block chaining
7
+ *
8
+ */
9
+
10
+#include <gpxe/crypto.h>
11
+
12
+/**
13
+ * Set key
14
+ *
15
+ * @v ctx		Context
16
+ * @v key		Key
17
+ * @v keylen		Key length
18
+ * @v cipher		Underlying cipher algorithm
19
+ * @v cbc_ctx		CBC context
20
+ * @ret rc		Return status code
21
+ */
22
+static inline int cbc_setkey ( void *ctx, const void *key, size_t keylen,
23
+			       struct cipher_algorithm *cipher,
24
+			       void *cbc_ctx __unused ) {
25
+
26
+	return cipher_setkey ( cipher, ctx, key, keylen );
27
+}
28
+
29
+/**
30
+ * Set initialisation vector
31
+ *
32
+ * @v ctx		Context
33
+ * @v iv		Initialisation vector
34
+ * @v cipher		Underlying cipher algorithm
35
+ * @v cbc_ctx		CBC context
36
+ */
37
+static inline void cbc_setiv ( void *ctx __unused, const void *iv,
38
+			       struct cipher_algorithm *cipher,
39
+			       void *cbc_ctx ) {
40
+	memcpy ( cbc_ctx, iv, cipher->blocksize );
41
+}
42
+
43
+extern void cbc_encrypt ( void *ctx, const void *src, void *dst,
44
+			  size_t len, struct cipher_algorithm *cipher,
45
+			  void *cbc_ctx );
46
+extern void cbc_decrypt ( void *ctx, const void *src, void *dst,
47
+			  size_t len, struct cipher_algorithm *cipher,
48
+			  void *cbc_ctx );
49
+
50
+#endif /* _GPXE_CBC_H */

Loading…
İptal
Kaydet