Browse Source

[crypto] Expose pem_asn1() for use with non-image data

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 7 years ago
parent
commit
14e3b4b29a
2 changed files with 81 additions and 42 deletions
  1. 74
    41
      src/image/pem.c
  2. 7
    1
      src/include/ipxe/pem.h

+ 74
- 41
src/image/pem.c View File

27
 #include <errno.h>
27
 #include <errno.h>
28
 #include <assert.h>
28
 #include <assert.h>
29
 #include <ipxe/asn1.h>
29
 #include <ipxe/asn1.h>
30
-#include <ipxe/pem.h>
31
 #include <ipxe/base64.h>
30
 #include <ipxe/base64.h>
32
 #include <ipxe/uaccess.h>
31
 #include <ipxe/uaccess.h>
33
 #include <ipxe/image.h>
32
 #include <ipxe/image.h>
33
+#include <ipxe/pem.h>
34
 
34
 
35
 /** @file
35
 /** @file
36
  *
36
  *
41
 /**
41
 /**
42
  * Locate next line
42
  * Locate next line
43
  *
43
  *
44
- * @v image		PEM image
44
+ * @v data		PEM data
45
+ * @v len		Length of PEM data
45
  * @v offset		Starting offset
46
  * @v offset		Starting offset
46
  * @ret next		Offset to next line
47
  * @ret next		Offset to next line
47
  */
48
  */
48
-static size_t pem_next ( struct image *image, size_t offset ) {
49
+static size_t pem_next ( userptr_t data, size_t len, size_t offset ) {
49
 	off_t eol;
50
 	off_t eol;
50
 
51
 
51
 	/* Find and skip next newline character, if any */
52
 	/* Find and skip next newline character, if any */
52
-	eol = memchr_user ( image->data, offset, '\n', ( image->len - offset ));
53
+	eol = memchr_user ( data, offset, '\n', ( len - offset ) );
53
 	if ( eol < 0 )
54
 	if ( eol < 0 )
54
-		return image->len;
55
+		return len;
55
 	return ( eol + 1 );
56
 	return ( eol + 1 );
56
 }
57
 }
57
 
58
 
58
 /**
59
 /**
59
  * Locate boundary marker line
60
  * Locate boundary marker line
60
  *
61
  *
61
- * @v image		PEM image
62
+ * @v data		PEM data
63
+ * @v len		Length of PEM data
62
  * @v offset		Starting offset
64
  * @v offset		Starting offset
63
  * @v marker		Boundary marker
65
  * @v marker		Boundary marker
64
  * @ret offset		Offset to boundary marker line, or negative error
66
  * @ret offset		Offset to boundary marker line, or negative error
65
  */
67
  */
66
-static int pem_marker ( struct image *image, size_t offset,
68
+static int pem_marker ( userptr_t data, size_t len, size_t offset,
67
 			const char *marker ) {
69
 			const char *marker ) {
68
 	char buf[ strlen ( marker ) ];
70
 	char buf[ strlen ( marker ) ];
69
 
71
 
70
 	/* Sanity check */
72
 	/* Sanity check */
71
-	assert ( offset <= image->len );
73
+	assert ( offset <= len );
72
 
74
 
73
 	/* Scan for marker at start of line */
75
 	/* Scan for marker at start of line */
74
-	while ( offset < image->len ) {
76
+	while ( offset < len ) {
75
 
77
 
76
 		/* Check for marker */
78
 		/* Check for marker */
77
-		if ( ( image->len - offset ) < sizeof ( buf ) )
79
+		if ( ( len - offset ) < sizeof ( buf ) )
78
 			break;
80
 			break;
79
-		copy_from_user ( buf, image->data, offset, sizeof ( buf ) );
81
+		copy_from_user ( buf, data, offset, sizeof ( buf ) );
80
 		if ( memcmp ( buf, marker, sizeof ( buf ) ) == 0 )
82
 		if ( memcmp ( buf, marker, sizeof ( buf ) ) == 0 )
81
 			return offset;
83
 			return offset;
82
 
84
 
83
 		/* Move to next line */
85
 		/* Move to next line */
84
-		offset = pem_next ( image, offset );
85
-		assert ( offset <= image->len );
86
+		offset = pem_next ( data, len, offset );
87
+		assert ( offset <= len );
86
 	}
88
 	}
87
 
89
 
88
 	return -ENOENT;
90
 	return -ENOENT;
89
 }
91
 }
90
 
92
 
91
 /**
93
 /**
92
- * Extract ASN.1 object from image
94
+ * Extract ASN.1 object from PEM data
93
  *
95
  *
94
- * @v image		PEM image
95
- * @v offset		Offset within image
96
+ * @v data		PEM data
97
+ * @v len		Length of PEM data
98
+ * @v offset		Offset within data
96
  * @v cursor		ASN.1 cursor to fill in
99
  * @v cursor		ASN.1 cursor to fill in
97
- * @ret next		Offset to next image, or negative error
100
+ * @ret next		Offset to next object, or negative error
98
  *
101
  *
99
  * The caller is responsible for eventually calling free() on the
102
  * The caller is responsible for eventually calling free() on the
100
  * allocated ASN.1 cursor.
103
  * allocated ASN.1 cursor.
101
  */
104
  */
102
-static int pem_asn1 ( struct image *image, size_t offset,
103
-		      struct asn1_cursor **cursor ) {
105
+int pem_asn1 ( userptr_t data, size_t len, size_t offset,
106
+	       struct asn1_cursor **cursor ) {
104
 	size_t encoded_len;
107
 	size_t encoded_len;
105
 	size_t decoded_max_len;
108
 	size_t decoded_max_len;
106
 	char *encoded;
109
 	char *encoded;
107
 	void *decoded;
110
 	void *decoded;
111
+	int decoded_len;
108
 	int begin;
112
 	int begin;
109
 	int end;
113
 	int end;
110
-	int len;
111
 	int rc;
114
 	int rc;
112
 
115
 
113
 	/* Locate and skip BEGIN marker */
116
 	/* Locate and skip BEGIN marker */
114
-	begin = pem_marker ( image, offset, PEM_BEGIN );
117
+	begin = pem_marker ( data, len, offset, PEM_BEGIN );
115
 	if ( begin < 0 ) {
118
 	if ( begin < 0 ) {
116
 		rc = begin;
119
 		rc = begin;
117
-		DBGC ( image, "PEM %s [%#zx,%#zx) missing BEGIN marker: %s\n",
118
-		       image->name, offset, image->len, strerror ( rc ) );
120
+		DBGC ( data, "PEM [%#zx,%#zx) missing BEGIN marker: %s\n",
121
+		       offset, len, strerror ( rc ) );
119
 		goto err_begin;
122
 		goto err_begin;
120
 	}
123
 	}
121
-	begin = pem_next ( image, begin );
124
+	begin = pem_next ( data, len, begin );
122
 
125
 
123
 	/* Locate and skip END marker */
126
 	/* Locate and skip END marker */
124
-	end = pem_marker ( image, begin, PEM_END );
127
+	end = pem_marker ( data, len, begin, PEM_END );
125
 	if ( end < 0 ) {
128
 	if ( end < 0 ) {
126
 		rc = end;
129
 		rc = end;
127
-		DBGC ( image, "PEM %s [%#zx,%#zx) missing END marker: %s\n",
128
-		       image->name, offset, image->len, strerror ( rc ) );
130
+		DBGC ( data, "PEM [%#zx,%#zx) missing END marker: %s\n",
131
+		       offset, len, strerror ( rc ) );
129
 		goto err_end;
132
 		goto err_end;
130
 	}
133
 	}
131
 	encoded_len = ( end - begin );
134
 	encoded_len = ( end - begin );
132
-	end = pem_next ( image, end );
135
+	end = pem_next ( data, len, end );
133
 
136
 
134
 	/* Extract Base64-encoded data */
137
 	/* Extract Base64-encoded data */
135
 	encoded = malloc ( encoded_len + 1 /* NUL */ );
138
 	encoded = malloc ( encoded_len + 1 /* NUL */ );
137
 		rc = -ENOMEM;
140
 		rc = -ENOMEM;
138
 		goto err_alloc_encoded;
141
 		goto err_alloc_encoded;
139
 	}
142
 	}
140
-	copy_from_user ( encoded, image->data, begin, encoded_len );
143
+	copy_from_user ( encoded, data, begin, encoded_len );
141
 	encoded[encoded_len] = '\0';
144
 	encoded[encoded_len] = '\0';
142
 
145
 
143
 	/* Allocate cursor and data buffer */
146
 	/* Allocate cursor and data buffer */
150
 	decoded = ( ( ( void * ) *cursor ) + sizeof ( **cursor ) );
153
 	decoded = ( ( ( void * ) *cursor ) + sizeof ( **cursor ) );
151
 
154
 
152
 	/* Decode Base64-encoded data */
155
 	/* Decode Base64-encoded data */
153
-	len = base64_decode ( encoded, decoded, decoded_max_len );
154
-	if ( len < 0 ) {
155
-		rc = len;
156
-		DBGC ( image, "PEM %s could not decode: %s\n",
157
-		       image->name, strerror ( rc ) );
156
+	decoded_len = base64_decode ( encoded, decoded, decoded_max_len );
157
+	if ( decoded_len < 0 ) {
158
+		rc = decoded_len;
159
+		DBGC ( data, "PEM could not decode: %s\n", strerror ( rc ) );
158
 		goto err_decode;
160
 		goto err_decode;
159
 	}
161
 	}
160
 	(*cursor)->data = decoded;
162
 	(*cursor)->data = decoded;
161
-	(*cursor)->len = len;
163
+	(*cursor)->len = decoded_len;
162
 	assert ( (*cursor)->len <= decoded_max_len );
164
 	assert ( (*cursor)->len <= decoded_max_len );
163
 
165
 
164
 	/* Free Base64-encoded data */
166
 	/* Free Base64-encoded data */
166
 
168
 
167
 	/* Update offset and skip any unencapsulated trailer */
169
 	/* Update offset and skip any unencapsulated trailer */
168
 	offset = end;
170
 	offset = end;
169
-	if ( pem_marker ( image, offset, PEM_BEGIN ) < 0 )
170
-		offset = image->len;
171
+	if ( pem_marker ( data, len, offset, PEM_BEGIN ) < 0 )
172
+		offset = len;
171
 
173
 
172
 	return offset;
174
 	return offset;
173
 
175
 
188
  * @v image		PEM image
190
  * @v image		PEM image
189
  * @ret rc		Return status code
191
  * @ret rc		Return status code
190
  */
192
  */
191
-static int pem_probe ( struct image *image ) {
193
+static int pem_image_probe ( struct image *image ) {
194
+	int offset;
192
 	int rc;
195
 	int rc;
193
 
196
 
194
 	/* Check that image contains a BEGIN marker */
197
 	/* Check that image contains a BEGIN marker */
195
-	if ( ( rc = pem_marker ( image, 0, PEM_BEGIN ) ) < 0 ) {
198
+	if ( ( offset = pem_marker ( image->data, image->len, 0,
199
+				     PEM_BEGIN ) ) < 0 ) {
200
+		rc = offset;
196
 		DBGC ( image, "PEM %s has no BEGIN marker: %s\n",
201
 		DBGC ( image, "PEM %s has no BEGIN marker: %s\n",
197
 		       image->name, strerror ( rc ) );
202
 		       image->name, strerror ( rc ) );
198
 		return rc;
203
 		return rc;
201
 	return 0;
206
 	return 0;
202
 }
207
 }
203
 
208
 
209
+/**
210
+ * Extract ASN.1 object from image
211
+ *
212
+ * @v image		PEM image
213
+ * @v offset		Offset within image
214
+ * @v cursor		ASN.1 cursor to fill in
215
+ * @ret next		Offset to next image, or negative error
216
+ *
217
+ * The caller is responsible for eventually calling free() on the
218
+ * allocated ASN.1 cursor.
219
+ */
220
+static int pem_image_asn1 ( struct image *image, size_t offset,
221
+			    struct asn1_cursor **cursor ) {
222
+	int next;
223
+	int rc;
224
+
225
+	/* Extract ASN.1 object */
226
+	if ( ( next = pem_asn1 ( image->data, image->len, offset,
227
+				 cursor ) ) < 0 ) {
228
+		rc = next;
229
+		DBGC ( image, "PEM %s could not extract ASN.1: %s\n",
230
+		       image->name, strerror ( rc ) );
231
+		return rc;
232
+	}
233
+
234
+	return next;
235
+}
236
+
204
 /** PEM image type */
237
 /** PEM image type */
205
 struct image_type pem_image_type __image_type ( PROBE_NORMAL ) = {
238
 struct image_type pem_image_type __image_type ( PROBE_NORMAL ) = {
206
 	.name = "PEM",
239
 	.name = "PEM",
207
-	.probe = pem_probe,
208
-	.asn1 = pem_asn1,
240
+	.probe = pem_image_probe,
241
+	.asn1 = pem_image_asn1,
209
 };
242
 };

+ 7
- 1
src/include/ipxe/pem.h View File

3
 
3
 
4
 /** @file
4
 /** @file
5
  *
5
  *
6
- * PEM image format
6
+ * PEM-encoded ASN.1 data
7
  *
7
  *
8
  */
8
  */
9
 
9
 
10
 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
10
 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
11
 
11
 
12
+#include <stdint.h>
13
+#include <ipxe/uaccess.h>
14
+#include <ipxe/asn1.h>
12
 #include <ipxe/image.h>
15
 #include <ipxe/image.h>
13
 
16
 
14
 /** Pre-encapsulation boundary marker */
17
 /** Pre-encapsulation boundary marker */
17
 /** Post-encapsulation boundary marker */
20
 /** Post-encapsulation boundary marker */
18
 #define PEM_END "-----END"
21
 #define PEM_END "-----END"
19
 
22
 
23
+extern int pem_asn1 ( userptr_t data, size_t len, size_t offset,
24
+		      struct asn1_cursor **cursor );
25
+
20
 extern struct image_type pem_image_type __image_type ( PROBE_NORMAL );
26
 extern struct image_type pem_image_type __image_type ( PROBE_NORMAL );
21
 
27
 
22
 #endif /* _IPXE_PEM_H */
28
 #endif /* _IPXE_PEM_H */

Loading…
Cancel
Save