[fdt] Add ability to parse a MAC address from a flattened device tree
[ipxe.git] / src / image / der.c
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 };