|
@@ -43,6 +43,14 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
43
|
43
|
__einfo_error ( EINFO_EINVAL_ASN1_LEN )
|
44
|
44
|
#define EINFO_EINVAL_ASN1_LEN \
|
45
|
45
|
__einfo_uniqify ( EINFO_EINVAL, 0x03, "Field overruns cursor" )
|
|
46
|
+#define EINVAL_ASN1_BOOLEAN \
|
|
47
|
+ __einfo_error ( EINFO_EINVAL_ASN1_BOOLEAN )
|
|
48
|
+#define EINFO_EINVAL_ASN1_BOOLEAN \
|
|
49
|
+ __einfo_uniqify ( EINFO_EINVAL, 0x04, "Invalid boolean" )
|
|
50
|
+#define EINVAL_ASN1_INTEGER \
|
|
51
|
+ __einfo_error ( EINFO_EINVAL_ASN1_INTEGER )
|
|
52
|
+#define EINFO_EINVAL_ASN1_INTEGER \
|
|
53
|
+ __einfo_uniqify ( EINFO_EINVAL, 0x04, "Invalid integer" )
|
46
|
54
|
|
47
|
55
|
/**
|
48
|
56
|
* Invalidate ASN.1 object cursor
|
|
@@ -191,7 +199,7 @@ int asn1_skip_if_exists ( struct asn1_cursor *cursor, unsigned int type ) {
|
191
|
199
|
int asn1_skip ( struct asn1_cursor *cursor, unsigned int type ) {
|
192
|
200
|
int rc;
|
193
|
201
|
|
194
|
|
- if ( ( rc = asn1_skip_if_exists ( cursor, type ) ) < 0 ) {
|
|
202
|
+ if ( ( rc = asn1_skip_if_exists ( cursor, type ) ) != 0 ) {
|
195
|
203
|
asn1_invalidate_cursor ( cursor );
|
196
|
204
|
return rc;
|
197
|
205
|
}
|
|
@@ -199,6 +207,32 @@ int asn1_skip ( struct asn1_cursor *cursor, unsigned int type ) {
|
199
|
207
|
return 0;
|
200
|
208
|
}
|
201
|
209
|
|
|
210
|
+/**
|
|
211
|
+ * Shrink ASN.1 cursor to fit object
|
|
212
|
+ *
|
|
213
|
+ * @v cursor ASN.1 object cursor
|
|
214
|
+ * @v type Expected type, or ASN1_ANY
|
|
215
|
+ * @ret rc Return status code
|
|
216
|
+ *
|
|
217
|
+ * The object cursor will be shrunk to contain only the current ASN.1
|
|
218
|
+ * object. If any error occurs, the object cursor will be
|
|
219
|
+ * invalidated.
|
|
220
|
+ */
|
|
221
|
+int asn1_shrink ( struct asn1_cursor *cursor, unsigned int type ) {
|
|
222
|
+ struct asn1_cursor next;
|
|
223
|
+ int rc;
|
|
224
|
+
|
|
225
|
+ /* Skip to next object */
|
|
226
|
+ memcpy ( &next, cursor, sizeof ( next ) );
|
|
227
|
+ if ( ( rc = asn1_skip ( &next, type ) ) != 0 )
|
|
228
|
+ return rc;
|
|
229
|
+
|
|
230
|
+ /* Shrink original cursor to contain only its first object */
|
|
231
|
+ cursor->len = ( next.data - cursor->data );
|
|
232
|
+
|
|
233
|
+ return 0;
|
|
234
|
+}
|
|
235
|
+
|
202
|
236
|
/**
|
203
|
237
|
* Enter ASN.1 object of any type
|
204
|
238
|
*
|
|
@@ -219,6 +253,76 @@ int asn1_skip_any ( struct asn1_cursor *cursor ) {
|
219
|
253
|
return asn1_skip ( cursor, ASN1_ANY );
|
220
|
254
|
}
|
221
|
255
|
|
|
256
|
+/**
|
|
257
|
+ * Shrink ASN.1 object of any type
|
|
258
|
+ *
|
|
259
|
+ * @v cursor ASN.1 object cursor
|
|
260
|
+ * @ret rc Return status code
|
|
261
|
+ */
|
|
262
|
+int asn1_shrink_any ( struct asn1_cursor *cursor ) {
|
|
263
|
+ return asn1_shrink ( cursor, ASN1_ANY );
|
|
264
|
+}
|
|
265
|
+
|
|
266
|
+/**
|
|
267
|
+ * Parse value of ASN.1 boolean
|
|
268
|
+ *
|
|
269
|
+ * @v cursor ASN.1 object cursor
|
|
270
|
+ * @ret value Value, or negative error
|
|
271
|
+ */
|
|
272
|
+int asn1_boolean ( const struct asn1_cursor *cursor ) {
|
|
273
|
+ struct asn1_cursor contents;
|
|
274
|
+ const struct asn1_boolean *boolean;
|
|
275
|
+
|
|
276
|
+ /* Enter boolean */
|
|
277
|
+ memcpy ( &contents, cursor, sizeof ( contents ) );
|
|
278
|
+ asn1_enter ( &contents, ASN1_BOOLEAN );
|
|
279
|
+ if ( contents.len != sizeof ( *boolean ) )
|
|
280
|
+ return -EINVAL_ASN1_BOOLEAN;
|
|
281
|
+
|
|
282
|
+ /* Extract value */
|
|
283
|
+ boolean = contents.data;
|
|
284
|
+ return boolean->value;
|
|
285
|
+}
|
|
286
|
+
|
|
287
|
+/**
|
|
288
|
+ * Parse value of ASN.1 integer
|
|
289
|
+ *
|
|
290
|
+ * @v cursor ASN.1 object cursor
|
|
291
|
+ * @v value Value to fill in
|
|
292
|
+ * @ret rc Return status code
|
|
293
|
+ */
|
|
294
|
+int asn1_integer ( const struct asn1_cursor *cursor, int *value ) {
|
|
295
|
+ struct asn1_cursor contents;
|
|
296
|
+ uint8_t high_byte;
|
|
297
|
+ int rc;
|
|
298
|
+
|
|
299
|
+ /* Enter integer */
|
|
300
|
+ memcpy ( &contents, cursor, sizeof ( contents ) );
|
|
301
|
+ if ( ( rc = asn1_enter ( &contents, ASN1_INTEGER ) ) != 0 )
|
|
302
|
+ return rc;
|
|
303
|
+ if ( contents.len < 1 )
|
|
304
|
+ return -EINVAL_ASN1_INTEGER;
|
|
305
|
+
|
|
306
|
+ /* Initialise value according to sign byte */
|
|
307
|
+ *value = *( ( int8_t * ) contents.data );
|
|
308
|
+ contents.data++;
|
|
309
|
+ contents.len--;
|
|
310
|
+
|
|
311
|
+ /* Process value */
|
|
312
|
+ while ( contents.len ) {
|
|
313
|
+ high_byte = ( (*value) >> ( 8 * ( sizeof ( *value ) - 1 ) ) );
|
|
314
|
+ if ( ( high_byte != 0x00 ) && ( high_byte != 0xff ) ) {
|
|
315
|
+ DBGC ( cursor, "ASN1 %p integer overflow\n", cursor );
|
|
316
|
+ return -EINVAL_ASN1_INTEGER;
|
|
317
|
+ }
|
|
318
|
+ *value = ( ( *value << 8 ) | *( ( uint8_t * ) contents.data ) );
|
|
319
|
+ contents.data++;
|
|
320
|
+ contents.len--;
|
|
321
|
+ }
|
|
322
|
+
|
|
323
|
+ return 0;
|
|
324
|
+}
|
|
325
|
+
|
222
|
326
|
/**
|
223
|
327
|
* Compare two ASN.1 objects
|
224
|
328
|
*
|