Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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>
- Loading branch information
Showing
9 changed files
with
396 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
/* | ||
* Copyright (C) 2016 Michael Brown <mbrown@fensystems.co.uk>. | ||
* | ||
* This program is free software; you can redistribute it and/or | ||
* modify it under the terms of the GNU General Public License as | ||
* published by the Free Software Foundation; either version 2 of the | ||
* License, or any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, but | ||
* WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
* General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program; if not, write to the Free Software | ||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
* 02110-1301, USA. | ||
* | ||
* You can also choose to distribute this program under the terms of | ||
* the Unmodified Binary Distribution Licence (as given in the file | ||
* COPYING.UBDL), provided that you have satisfied its requirements. | ||
*/ | ||
|
||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); | ||
|
||
#include <stdlib.h> | ||
#include <errno.h> | ||
#include <assert.h> | ||
#include <ipxe/asn1.h> | ||
#include <ipxe/der.h> | ||
#include <ipxe/uaccess.h> | ||
#include <ipxe/image.h> | ||
|
||
/** @file | ||
* | ||
* DER-encoded ASN.1 data | ||
* | ||
*/ | ||
|
||
/** | ||
* Extract ASN.1 object from image | ||
* | ||
* @v image DER image | ||
* @v offset Offset within image | ||
* @v cursor ASN.1 cursor to fill in | ||
* @ret next Offset to next image, or negative error | ||
* | ||
* The caller is responsible for eventually calling free() on the | ||
* allocated ASN.1 cursor. | ||
*/ | ||
static int der_asn1 ( struct image *image, size_t offset __unused, | ||
struct asn1_cursor **cursor ) { | ||
void *data; | ||
|
||
/* Allocate cursor and data buffer */ | ||
*cursor = malloc ( sizeof ( **cursor ) + image->len ); | ||
if ( ! *cursor ) | ||
return -ENOMEM; | ||
data = ( ( ( void * ) *cursor ) + sizeof ( **cursor ) ); | ||
|
||
/* Populate cursor and data buffer */ | ||
(*cursor)->data = data; | ||
(*cursor)->len = image->len; | ||
copy_from_user ( data, image->data, 0, image->len ); | ||
|
||
return image->len; | ||
} | ||
|
||
/** | ||
* Probe DER image | ||
* | ||
* @v image DER image | ||
* @ret rc Return status code | ||
*/ | ||
static int der_probe ( struct image *image ) { | ||
struct asn1_cursor cursor; | ||
uint8_t buf[8]; | ||
size_t extra; | ||
size_t total; | ||
int len; | ||
int rc; | ||
|
||
/* Sanity check: no realistic DER image can be smaller than this */ | ||
if ( image->len < sizeof ( buf ) ) | ||
return -ENOEXEC; | ||
|
||
/* Prepare partial cursor */ | ||
cursor.data = buf; | ||
cursor.len = sizeof ( buf ); | ||
copy_from_user ( buf, image->data, 0, sizeof ( buf ) ); | ||
extra = ( image->len - sizeof ( buf ) ); | ||
|
||
/* Get length of ASN.1 sequence */ | ||
len = asn1_start ( &cursor, ASN1_SEQUENCE, extra ); | ||
if ( len < 0 ) { | ||
rc = len; | ||
DBGC ( image, "DER %s is not valid ASN.1: %s\n", | ||
image->name, strerror ( rc ) ); | ||
return rc; | ||
} | ||
|
||
/* Add length of tag and length bytes consumed by asn1_start() */ | ||
total = ( len + ( cursor.data - ( ( void * ) buf ) ) ); | ||
assert ( total <= image->len ); | ||
|
||
/* Check that image comprises a single well-formed ASN.1 object */ | ||
if ( total != image->len ) { | ||
DBGC ( image, "DER %s is not single ASN.1\n", image->name ); | ||
return -ENOEXEC; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
/** DER image type */ | ||
struct image_type der_image_type __image_type ( PROBE_NORMAL ) = { | ||
.name = "DER", | ||
.probe = der_probe, | ||
.asn1 = der_asn1, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
#ifndef _IPXE_DER_H | ||
#define _IPXE_DER_H | ||
|
||
/** @file | ||
* | ||
* DER image format | ||
* | ||
*/ | ||
|
||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); | ||
|
||
#include <ipxe/image.h> | ||
|
||
extern struct image_type der_image_type __image_type ( PROBE_NORMAL ); | ||
|
||
#endif /* _IPXE_DER_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
/* | ||
* Copyright (C) 2016 Michael Brown <mbrown@fensystems.co.uk>. | ||
* | ||
* This program is free software; you can redistribute it and/or | ||
* modify it under the terms of the GNU General Public License as | ||
* published by the Free Software Foundation; either version 2 of the | ||
* License, or any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, but | ||
* WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
* General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program; if not, write to the Free Software | ||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
* 02110-1301, USA. | ||
* | ||
* You can also choose to distribute this program under the terms of | ||
* the Unmodified Binary Distribution Licence (as given in the file | ||
* COPYING.UBDL), provided that you have satisfied its requirements. | ||
*/ | ||
|
||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); | ||
|
||
/** @file | ||
* | ||
* ASN.1 self-tests | ||
* | ||
*/ | ||
|
||
/* Forcibly enable assertions */ | ||
#undef NDEBUG | ||
|
||
#include <stdlib.h> | ||
#include <assert.h> | ||
#include <ipxe/image.h> | ||
#include <ipxe/asn1.h> | ||
#include <ipxe/test.h> | ||
#include "asn1_test.h" | ||
|
||
/** | ||
* Report ASN.1 test result | ||
* | ||
* @v test ASN.1 test | ||
* @v file Test code file | ||
* @v line Test code line | ||
*/ | ||
void asn1_okx ( struct asn1_test *test, const char *file, unsigned int line ) { | ||
struct digest_algorithm *digest = &asn1_test_digest_algorithm; | ||
struct asn1_cursor *cursor; | ||
uint8_t ctx[digest->ctxsize]; | ||
uint8_t out[ASN1_TEST_DIGEST_SIZE]; | ||
unsigned int i; | ||
size_t offset; | ||
int next; | ||
|
||
/* Sanity check */ | ||
assert ( sizeof ( out ) == digest->digestsize ); | ||
|
||
/* Correct image data pointer */ | ||
test->image->data = virt_to_user ( ( void * ) test->image->data ); | ||
|
||
/* Check that image is detected as correct type */ | ||
okx ( register_image ( test->image ) == 0, file, line ); | ||
okx ( test->image->type == test->type, file, line ); | ||
|
||
/* Check that all ASN.1 objects can be extracted */ | ||
for ( offset = 0, i = 0 ; i < test->count ; offset = next, i++ ) { | ||
|
||
/* Extract ASN.1 object */ | ||
next = image_asn1 ( test->image, offset, &cursor ); | ||
okx ( next >= 0, file, line ); | ||
okx ( ( ( size_t ) next ) > offset, file, line ); | ||
if ( next > 0 ) { | ||
|
||
/* Calculate digest of ASN.1 object */ | ||
digest_init ( digest, ctx ); | ||
digest_update ( digest, ctx, cursor->data, | ||
cursor->len ); | ||
digest_final ( digest, ctx, out ); | ||
|
||
/* Compare against expected digest */ | ||
okx ( memcmp ( out, test->expected[i].digest, | ||
sizeof ( out ) ) == 0, file, line ); | ||
|
||
/* Free ASN.1 object */ | ||
free ( cursor ); | ||
} | ||
} | ||
|
||
/* Check that we have reached the end of the image */ | ||
okx ( offset == test->image->len, file, line ); | ||
|
||
/* Unregister image */ | ||
unregister_image ( test->image ); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
#ifndef _ASN1_TEST_H | ||
#define _ASN1_TEST_H | ||
|
||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); | ||
|
||
#include <stdint.h> | ||
#include <ipxe/image.h> | ||
#include <ipxe/sha1.h> | ||
#include <ipxe/test.h> | ||
|
||
/** Digest algorithm used for ASN.1 tests */ | ||
#define asn1_test_digest_algorithm sha1_algorithm | ||
|
||
/** Digest size used for ASN.1 tests */ | ||
#define ASN1_TEST_DIGEST_SIZE SHA1_DIGEST_SIZE | ||
|
||
/** An ASN.1 test digest */ | ||
struct asn1_test_digest { | ||
/** Digest value */ | ||
uint8_t digest[ASN1_TEST_DIGEST_SIZE]; | ||
}; | ||
|
||
/** An ASN.1 test */ | ||
struct asn1_test { | ||
/** Image type */ | ||
struct image_type *type; | ||
/** Source image */ | ||
struct image *image; | ||
/** Expected digests of ASN.1 objects */ | ||
struct asn1_test_digest *expected; | ||
/** Number of ASN.1 objects */ | ||
unsigned int count; | ||
}; | ||
|
||
/** | ||
* Define an ASN.1 test | ||
* | ||
* @v _name Test name | ||
* @v _type Test image file type | ||
* @v _file Test image file data | ||
* @v ... Expected ASN.1 object digests | ||
* @ret test ASN.1 test | ||
*/ | ||
#define ASN1( _name, _type, _file, ... ) \ | ||
static const char _name ## __file[] = _file; \ | ||
static struct image _name ## __image = { \ | ||
.refcnt = REF_INIT ( ref_no_free ), \ | ||
.name = #_name, \ | ||
.data = ( userptr_t ) ( _name ## __file ), \ | ||
.len = sizeof ( _name ## __file ), \ | ||
}; \ | ||
static struct asn1_test_digest _name ## _expected[] = { \ | ||
__VA_ARGS__ \ | ||
}; \ | ||
static struct asn1_test _name = { \ | ||
.type = _type, \ | ||
.image = & _name ## __image, \ | ||
.expected = _name ## _expected, \ | ||
.count = ( sizeof ( _name ## _expected ) / \ | ||
sizeof ( _name ## _expected[0] ) ), \ | ||
}; | ||
|
||
extern void asn1_okx ( struct asn1_test *test, const char *file, | ||
unsigned int line ); | ||
|
||
/** | ||
* Report ASN.1 test result | ||
* | ||
* @v test ASN.1 test | ||
*/ | ||
#define asn1_ok( test ) asn1_okx ( test, __FILE__, __LINE__ ) | ||
|
||
#endif /* _ASN1_TEST_H */ |
Oops, something went wrong.