Browse Source

[crypto] Add DER image format

Add DER-encoded ASN.1 as an image format.  There is no fixed signature
for DER files.  We treat an image as DER if it comprises a single
valid SEQUENCE object covering the entire length of the image.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 7 years ago
parent
commit
eb7188d04b

+ 3
- 0
src/config/config.c View File

@@ -188,6 +188,9 @@ REQUIRE_OBJECT ( pnm );
188 188
 #ifdef IMAGE_PNG
189 189
 REQUIRE_OBJECT ( png );
190 190
 #endif
191
+#ifdef IMAGE_DER
192
+REQUIRE_OBJECT ( der );
193
+#endif
191 194
 
192 195
 /*
193 196
  * Drag in all requested commands

+ 1
- 0
src/config/general.h View File

@@ -112,6 +112,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
112 112
 //#define	IMAGE_SDI		/* SDI image support */
113 113
 //#define	IMAGE_PNM		/* PNM image support */
114 114
 //#define	IMAGE_PNG		/* PNG image support */
115
+//#define	IMAGE_DER		/* DER image support */
115 116
 
116 117
 /*
117 118
  * Command-line commands to include

+ 120
- 0
src/image/der.c View File

@@ -0,0 +1,120 @@
1
+/*
2
+ * Copyright (C) 2016 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., 51 Franklin Street, Fifth Floor, Boston, MA
17
+ * 02110-1301, USA.
18
+ *
19
+ * You can also choose to distribute this program under the terms of
20
+ * the Unmodified Binary Distribution Licence (as given in the file
21
+ * COPYING.UBDL), provided that you have satisfied its requirements.
22
+ */
23
+
24
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
+
26
+#include <stdlib.h>
27
+#include <errno.h>
28
+#include <assert.h>
29
+#include <ipxe/asn1.h>
30
+#include <ipxe/der.h>
31
+#include <ipxe/uaccess.h>
32
+#include <ipxe/image.h>
33
+
34
+/** @file
35
+ *
36
+ * DER-encoded ASN.1 data
37
+ *
38
+ */
39
+
40
+/**
41
+ * Extract ASN.1 object from image
42
+ *
43
+ * @v image		DER image
44
+ * @v offset		Offset within image
45
+ * @v cursor		ASN.1 cursor to fill in
46
+ * @ret next		Offset to next image, or negative error
47
+ *
48
+ * The caller is responsible for eventually calling free() on the
49
+ * allocated ASN.1 cursor.
50
+ */
51
+static int der_asn1 ( struct image *image, size_t offset __unused,
52
+		      struct asn1_cursor **cursor ) {
53
+	void *data;
54
+
55
+	/* Allocate cursor and data buffer */
56
+	*cursor = malloc ( sizeof ( **cursor ) + image->len );
57
+	if ( ! *cursor )
58
+		return -ENOMEM;
59
+	data = ( ( ( void * ) *cursor ) + sizeof ( **cursor ) );
60
+
61
+	/* Populate cursor and data buffer */
62
+	(*cursor)->data = data;
63
+	(*cursor)->len = image->len;
64
+	copy_from_user ( data, image->data, 0, image->len );
65
+
66
+	return image->len;
67
+}
68
+
69
+/**
70
+ * Probe DER image
71
+ *
72
+ * @v image		DER image
73
+ * @ret rc		Return status code
74
+ */
75
+static int der_probe ( struct image *image ) {
76
+	struct asn1_cursor cursor;
77
+	uint8_t buf[8];
78
+	size_t extra;
79
+	size_t total;
80
+	int len;
81
+	int rc;
82
+
83
+	/* Sanity check: no realistic DER image can be smaller than this */
84
+	if ( image->len < sizeof ( buf ) )
85
+		return -ENOEXEC;
86
+
87
+	/* Prepare partial cursor */
88
+	cursor.data = buf;
89
+	cursor.len = sizeof ( buf );
90
+	copy_from_user ( buf, image->data, 0, sizeof ( buf ) );
91
+	extra = ( image->len - sizeof ( buf ) );
92
+
93
+	/* Get length of ASN.1 sequence */
94
+	len = asn1_start ( &cursor, ASN1_SEQUENCE, extra );
95
+	if ( len < 0 ) {
96
+		rc = len;
97
+		DBGC ( image, "DER %s is not valid ASN.1: %s\n",
98
+		       image->name, strerror ( rc ) );
99
+		return rc;
100
+	}
101
+
102
+	/* Add length of tag and length bytes consumed by asn1_start() */
103
+	total = ( len + ( cursor.data - ( ( void * ) buf ) ) );
104
+	assert ( total <= image->len );
105
+
106
+	/* Check that image comprises a single well-formed ASN.1 object */
107
+	if ( total != image->len ) {
108
+		DBGC ( image, "DER %s is not single ASN.1\n", image->name );
109
+		return -ENOEXEC;
110
+	}
111
+
112
+	return 0;
113
+}
114
+
115
+/** DER image type */
116
+struct image_type der_image_type __image_type ( PROBE_NORMAL ) = {
117
+	.name = "DER",
118
+	.probe = der_probe,
119
+	.asn1 = der_asn1,
120
+};

+ 16
- 0
src/include/ipxe/der.h View File

@@ -0,0 +1,16 @@
1
+#ifndef _IPXE_DER_H
2
+#define _IPXE_DER_H
3
+
4
+/** @file
5
+ *
6
+ * DER image format
7
+ *
8
+ */
9
+
10
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
11
+
12
+#include <ipxe/image.h>
13
+
14
+extern struct image_type der_image_type __image_type ( PROBE_NORMAL );
15
+
16
+#endif /* _IPXE_DER_H */

+ 1
- 0
src/include/ipxe/errfile.h View File

@@ -276,6 +276,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
276 276
 #define ERRFILE_embedded	      ( ERRFILE_IMAGE | 0x00050000 )
277 277
 #define ERRFILE_pnm		      ( ERRFILE_IMAGE | 0x00060000 )
278 278
 #define ERRFILE_png		      ( ERRFILE_IMAGE | 0x00070000 )
279
+#define ERRFILE_der		      ( ERRFILE_IMAGE | 0x00080000 )
279 280
 
280 281
 #define ERRFILE_asn1		      ( ERRFILE_OTHER | 0x00000000 )
281 282
 #define ERRFILE_chap		      ( ERRFILE_OTHER | 0x00010000 )

+ 97
- 0
src/tests/asn1_test.c View File

@@ -0,0 +1,97 @@
1
+/*
2
+ * Copyright (C) 2016 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., 51 Franklin Street, Fifth Floor, Boston, MA
17
+ * 02110-1301, USA.
18
+ *
19
+ * You can also choose to distribute this program under the terms of
20
+ * the Unmodified Binary Distribution Licence (as given in the file
21
+ * COPYING.UBDL), provided that you have satisfied its requirements.
22
+ */
23
+
24
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
+
26
+/** @file
27
+ *
28
+ * ASN.1 self-tests
29
+ *
30
+ */
31
+
32
+/* Forcibly enable assertions */
33
+#undef NDEBUG
34
+
35
+#include <stdlib.h>
36
+#include <assert.h>
37
+#include <ipxe/image.h>
38
+#include <ipxe/asn1.h>
39
+#include <ipxe/test.h>
40
+#include "asn1_test.h"
41
+
42
+/**
43
+ * Report ASN.1 test result
44
+ *
45
+ * @v test		ASN.1 test
46
+ * @v file		Test code file
47
+ * @v line		Test code line
48
+ */
49
+void asn1_okx ( struct asn1_test *test, const char *file, unsigned int line ) {
50
+	struct digest_algorithm *digest = &asn1_test_digest_algorithm;
51
+	struct asn1_cursor *cursor;
52
+	uint8_t ctx[digest->ctxsize];
53
+	uint8_t out[ASN1_TEST_DIGEST_SIZE];
54
+	unsigned int i;
55
+	size_t offset;
56
+	int next;
57
+
58
+	/* Sanity check */
59
+	assert ( sizeof ( out ) == digest->digestsize );
60
+
61
+	/* Correct image data pointer */
62
+	test->image->data = virt_to_user ( ( void * ) test->image->data );
63
+
64
+	/* Check that image is detected as correct type */
65
+	okx ( register_image ( test->image ) == 0, file, line );
66
+	okx ( test->image->type == test->type, file, line );
67
+
68
+	/* Check that all ASN.1 objects can be extracted */
69
+	for ( offset = 0, i = 0 ; i < test->count ; offset = next, i++ ) {
70
+
71
+		/* Extract ASN.1 object */
72
+		next = image_asn1 ( test->image, offset, &cursor );
73
+		okx ( next >= 0, file, line );
74
+		okx ( ( ( size_t ) next ) > offset, file, line );
75
+		if ( next > 0 ) {
76
+
77
+			/* Calculate digest of ASN.1 object */
78
+			digest_init ( digest, ctx );
79
+			digest_update ( digest, ctx, cursor->data,
80
+					cursor->len );
81
+			digest_final ( digest, ctx, out );
82
+
83
+			/* Compare against expected digest */
84
+			okx ( memcmp ( out, test->expected[i].digest,
85
+				       sizeof ( out ) ) == 0, file, line );
86
+
87
+			/* Free ASN.1 object */
88
+			free ( cursor );
89
+		}
90
+	}
91
+
92
+	/* Check that we have reached the end of the image */
93
+	okx ( offset == test->image->len, file, line );
94
+
95
+	/* Unregister image */
96
+	unregister_image ( test->image );
97
+}

+ 73
- 0
src/tests/asn1_test.h View File

@@ -0,0 +1,73 @@
1
+#ifndef _ASN1_TEST_H
2
+#define _ASN1_TEST_H
3
+
4
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
5
+
6
+#include <stdint.h>
7
+#include <ipxe/image.h>
8
+#include <ipxe/sha1.h>
9
+#include <ipxe/test.h>
10
+
11
+/** Digest algorithm used for ASN.1 tests */
12
+#define asn1_test_digest_algorithm sha1_algorithm
13
+
14
+/** Digest size used for ASN.1 tests */
15
+#define ASN1_TEST_DIGEST_SIZE SHA1_DIGEST_SIZE
16
+
17
+/** An ASN.1 test digest */
18
+struct asn1_test_digest {
19
+	/** Digest value */
20
+	uint8_t digest[ASN1_TEST_DIGEST_SIZE];
21
+};
22
+
23
+/** An ASN.1 test */
24
+struct asn1_test {
25
+	/** Image type */
26
+	struct image_type *type;
27
+	/** Source image */
28
+	struct image *image;
29
+	/** Expected digests of ASN.1 objects */
30
+	struct asn1_test_digest *expected;
31
+	/** Number of ASN.1 objects */
32
+	unsigned int count;
33
+};
34
+
35
+/**
36
+ * Define an ASN.1 test
37
+ *
38
+ * @v _name		Test name
39
+ * @v _type		Test image file type
40
+ * @v _file		Test image file data
41
+ * @v ...		Expected ASN.1 object digests
42
+ * @ret test		ASN.1 test
43
+ */
44
+#define ASN1( _name, _type, _file, ... )				\
45
+	static const char _name ## __file[] = _file;			\
46
+	static struct image _name ## __image = {			\
47
+		.refcnt = REF_INIT ( ref_no_free ),			\
48
+		.name = #_name,						\
49
+		.data = ( userptr_t ) ( _name ## __file ),		\
50
+		.len = sizeof ( _name ## __file ),			\
51
+	};								\
52
+	static struct asn1_test_digest _name ## _expected[] = {		\
53
+		__VA_ARGS__						\
54
+	};								\
55
+	static struct asn1_test _name = {				\
56
+		.type = _type,						\
57
+		.image = & _name ## __image,				\
58
+		.expected = _name ## _expected,				\
59
+		.count = ( sizeof ( _name ## _expected ) /		\
60
+			   sizeof ( _name ## _expected[0] ) ),		\
61
+	};
62
+
63
+extern void asn1_okx ( struct asn1_test *test, const char *file,
64
+		       unsigned int line );
65
+
66
+/**
67
+ * Report ASN.1 test result
68
+ *
69
+ * @v test		ASN.1 test
70
+ */
71
+#define asn1_ok( test ) asn1_okx ( test, __FILE__, __LINE__ )
72
+
73
+#endif /* _ASN1_TEST_H */

+ 84
- 0
src/tests/der_test.c View File

@@ -0,0 +1,84 @@
1
+/*
2
+ * Copyright (C) 2016 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., 51 Franklin Street, Fifth Floor, Boston, MA
17
+ * 02110-1301, USA.
18
+ *
19
+ * You can also choose to distribute this program under the terms of
20
+ * the Unmodified Binary Distribution Licence (as given in the file
21
+ * COPYING.UBDL), provided that you have satisfied its requirements.
22
+ */
23
+
24
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
+
26
+/** @file
27
+ *
28
+ * DER self-tests
29
+ *
30
+ */
31
+
32
+/* Forcibly enable assertions */
33
+#undef NDEBUG
34
+
35
+#include <string.h>
36
+#include <assert.h>
37
+#include <ipxe/test.h>
38
+#include <ipxe/der.h>
39
+#include "asn1_test.h"
40
+
41
+/** Define inline data */
42
+#define DATA(...) { __VA_ARGS__ }
43
+
44
+/** Define inline expected digest */
45
+#define DIGEST(...) { { __VA_ARGS__ } }
46
+
47
+/** 32-bit RSA private key */
48
+ASN1 ( rsa32, &der_image_type,
49
+       DATA ( 0x30, 0x2c, 0x02, 0x01, 0x00, 0x02, 0x05, 0x00, 0xb7, 0x56,
50
+	      0x5c, 0xb1, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x04, 0x66,
51
+	      0xa4, 0xc4, 0x35, 0x02, 0x03, 0x00, 0xda, 0x9f, 0x02, 0x03,
52
+	      0x00, 0xd6, 0xaf, 0x02, 0x02, 0x01, 0x59, 0x02, 0x02, 0x4e,
53
+	      0xe1, 0x02, 0x03, 0x00, 0xa6, 0x5a ),
54
+       DIGEST ( 0x82, 0x66, 0x24, 0xd9, 0xc3, 0x98, 0x1e, 0x5e, 0x56, 0xed,
55
+		0xd0, 0xd0, 0x2a, 0x5e, 0x9c, 0x3a, 0x58, 0xdf, 0x76, 0x0d ) );
56
+
57
+/** 64-bit RSA private key */
58
+ASN1 ( rsa64, &der_image_type,
59
+       DATA ( 0x30, 0x3e, 0x02, 0x01, 0x00, 0x02, 0x09, 0x00, 0xa1, 0xba,
60
+	      0xb5, 0x70, 0x00, 0x89, 0xc0, 0x43, 0x02, 0x03, 0x01, 0x00,
61
+	      0x01, 0x02, 0x08, 0x43, 0x98, 0xc6, 0x3c, 0x5f, 0xdc, 0x98,
62
+	      0x01, 0x02, 0x05, 0x00, 0xcf, 0x91, 0x1c, 0x5d, 0x02, 0x05,
63
+	      0x00, 0xc7, 0x77, 0x85, 0x1f, 0x02, 0x05, 0x00, 0xbc, 0xb3,
64
+	      0x33, 0x91, 0x02, 0x04, 0x1b, 0xf9, 0x38, 0x13, 0x02, 0x04,
65
+	      0x19, 0xf2, 0x58, 0x86 ),
66
+       DIGEST ( 0xee, 0x17, 0x32, 0x31, 0xf0, 0x3d, 0xfd, 0xaa, 0x9b, 0x47,
67
+		0xaf, 0x7b, 0x4b, 0x52, 0x0b, 0xb1, 0xab, 0x25, 0x3f, 0x11 ) );
68
+
69
+/**
70
+ * Perform DER self-test
71
+ *
72
+ */
73
+static void der_test_exec ( void ) {
74
+
75
+	/* Perform tests */
76
+	asn1_ok ( &rsa32 );
77
+	asn1_ok ( &rsa64 );
78
+}
79
+
80
+/** DER self-test */
81
+struct self_test der_test __self_test = {
82
+	.name = "der",
83
+	.exec = der_test_exec,
84
+};

+ 1
- 0
src/tests/tests.c View File

@@ -69,3 +69,4 @@ REQUIRE_OBJECT ( pccrc_test );
69 69
 REQUIRE_OBJECT ( linebuf_test );
70 70
 REQUIRE_OBJECT ( iobuf_test );
71 71
 REQUIRE_OBJECT ( bitops_test );
72
+REQUIRE_OBJECT ( der_test );

Loading…
Cancel
Save