1  /*
2   * ASN.1 DER parsing
3   * Copyright (c) 2006-2014, Jouni Malinen <j@w1.fi>
4   *
5   * This software may be distributed under the terms of the BSD license.
6   * See README for more details.
7   */
8  
9  #include "includes.h"
10  
11  #include "common.h"
12  #include "utils/wpabuf.h"
13  #include "asn1.h"
14  
15  const struct asn1_oid asn1_sha1_oid = {
16  	.oid = { 1, 3, 14, 3, 2, 26 },
17  	.len = 6
18  };
19  
20  const struct asn1_oid asn1_sha256_oid = {
21  	.oid = { 2, 16, 840, 1, 101, 3, 4, 2, 1 },
22  	.len = 9
23  };
24  
25  const struct asn1_oid asn1_ec_public_key_oid = {
26  	.oid = { 1, 2, 840, 10045, 2, 1 },
27  	.len = 6
28  };
29  
30  const struct asn1_oid asn1_prime256v1_oid = {
31  	.oid = { 1, 2, 840, 10045, 3, 1, 7 },
32  	.len = 7
33  };
34  
35  const struct asn1_oid asn1_secp384r1_oid = {
36  	.oid = { 1, 3, 132, 0, 34 },
37  	.len = 5
38  };
39  
40  const struct asn1_oid asn1_secp521r1_oid = {
41  	.oid = { 1, 3, 132, 0, 35 },
42  	.len = 5
43  };
44  
45  const struct asn1_oid asn1_brainpoolP256r1_oid = {
46  	.oid = { 1, 3, 36, 3, 3, 2, 8, 1, 1, 7 },
47  	.len = 10
48  };
49  
50  const struct asn1_oid asn1_brainpoolP384r1_oid = {
51  	.oid = { 1, 3, 36, 3, 3, 2, 8, 1, 1, 11 },
52  	.len = 10
53  };
54  
55  const struct asn1_oid asn1_brainpoolP512r1_oid = {
56  	.oid = { 1, 3, 36, 3, 3, 2, 8, 1, 1, 13 },
57  	.len = 10
58  };
59  
60  const struct asn1_oid asn1_aes_siv_cmac_aead_256_oid = {
61  	.oid = { 1, 2, 840, 113549, 1, 9, 16, 3, 22 },
62  	.len = 9
63  };
64  
65  const struct asn1_oid asn1_aes_siv_cmac_aead_384_oid = {
66  	.oid = { 1, 2, 840, 113549, 1, 9, 16, 3, 23 },
67  	.len = 9
68  };
69  
70  const struct asn1_oid asn1_aes_siv_cmac_aead_512_oid = {
71  	.oid = { 1, 2, 840, 113549, 1, 9, 16, 3, 24 },
72  	.len = 9
73  };
74  
75  const struct asn1_oid asn1_pbkdf2_oid = {
76  	.oid = { 1, 2, 840, 113549, 1, 5, 12 },
77  	.len = 7
78  };
79  
80  const struct asn1_oid asn1_pbkdf2_hmac_sha256_oid = {
81  	.oid = { 1, 2, 840, 113549, 2, 9 },
82  	.len = 6
83  };
84  
85  const struct asn1_oid asn1_pbkdf2_hmac_sha384_oid = {
86  	.oid = { 1, 2, 840, 113549, 2, 10 },
87  	.len = 6
88  };
89  
90  const struct asn1_oid asn1_pbkdf2_hmac_sha512_oid = {
91  	.oid = { 1, 2, 840, 113549, 2, 11 },
92  	.len = 6
93  };
94  
95  const struct asn1_oid asn1_dpp_config_params_oid = {
96  	.oid = { 1, 3, 6, 1, 4, 1, 40808, 1, 2, 1 },
97  	.len = 10
98  };
99  
100  const struct asn1_oid asn1_dpp_asymmetric_key_package_oid = {
101  	.oid = { 1, 3, 6, 1, 4, 1, 40808, 1, 2, 2 },
102  	.len = 10
103  };
104  
105  
asn1_valid_der_boolean(struct asn1_hdr * hdr)106  static int asn1_valid_der_boolean(struct asn1_hdr *hdr)
107  {
108  	/* Enforce DER requirements for a single way of encoding a BOOLEAN */
109  	if (hdr->length != 1) {
110  		wpa_printf(MSG_DEBUG, "ASN.1: Unexpected BOOLEAN length (%u)",
111  			   hdr->length);
112  		return 0;
113  	}
114  
115  	if (hdr->payload[0] != 0 && hdr->payload[0] != 0xff) {
116  		wpa_printf(MSG_DEBUG,
117  			   "ASN.1: Invalid BOOLEAN value 0x%x (DER requires 0 or 0xff)",
118  			   hdr->payload[0]);
119  		return 0;
120  	}
121  
122  	return 1;
123  }
124  
125  
asn1_valid_der(struct asn1_hdr * hdr)126  static int asn1_valid_der(struct asn1_hdr *hdr)
127  {
128  	if (hdr->class != ASN1_CLASS_UNIVERSAL)
129  		return 1;
130  	if (hdr->tag == ASN1_TAG_BOOLEAN && !asn1_valid_der_boolean(hdr))
131  		return 0;
132  	if (hdr->tag == ASN1_TAG_NULL && hdr->length != 0)
133  		return 0;
134  
135  	/* Check for allowed primitive/constructed values */
136  	if (hdr->constructed &&
137  	    (hdr->tag == ASN1_TAG_BOOLEAN ||
138  	     hdr->tag == ASN1_TAG_INTEGER ||
139  	     hdr->tag == ASN1_TAG_NULL ||
140  	     hdr->tag == ASN1_TAG_OID ||
141  	     hdr->tag == ANS1_TAG_RELATIVE_OID ||
142  	     hdr->tag == ASN1_TAG_REAL ||
143  	     hdr->tag == ASN1_TAG_ENUMERATED ||
144  	     hdr->tag == ASN1_TAG_BITSTRING ||
145  	     hdr->tag == ASN1_TAG_OCTETSTRING ||
146  	     hdr->tag == ASN1_TAG_NUMERICSTRING ||
147  	     hdr->tag == ASN1_TAG_PRINTABLESTRING ||
148  	     hdr->tag == ASN1_TAG_T61STRING ||
149  	     hdr->tag == ASN1_TAG_VIDEOTEXSTRING ||
150  	     hdr->tag == ASN1_TAG_VISIBLESTRING ||
151  	     hdr->tag == ASN1_TAG_IA5STRING ||
152  	     hdr->tag == ASN1_TAG_GRAPHICSTRING ||
153  	     hdr->tag == ASN1_TAG_GENERALSTRING ||
154  	     hdr->tag == ASN1_TAG_UNIVERSALSTRING ||
155  	     hdr->tag == ASN1_TAG_UTF8STRING ||
156  	     hdr->tag == ASN1_TAG_BMPSTRING ||
157  	     hdr->tag == ASN1_TAG_CHARACTERSTRING ||
158  	     hdr->tag == ASN1_TAG_UTCTIME ||
159  	     hdr->tag == ASN1_TAG_GENERALIZEDTIME ||
160  	     hdr->tag == ASN1_TAG_TIME))
161  		return 0;
162  	if (!hdr->constructed &&
163  	    (hdr->tag == ASN1_TAG_SEQUENCE ||
164  	     hdr->tag == ASN1_TAG_SET))
165  		return 0;
166  
167  	return 1;
168  }
169  
170  
asn1_get_next(const u8 * buf,size_t len,struct asn1_hdr * hdr)171  int asn1_get_next(const u8 *buf, size_t len, struct asn1_hdr *hdr)
172  {
173  	const u8 *pos, *end;
174  	u8 tmp;
175  
176  	os_memset(hdr, 0, sizeof(*hdr));
177  	pos = buf;
178  	end = buf + len;
179  
180  	if (pos >= end) {
181  		wpa_printf(MSG_DEBUG, "ASN.1: No room for Identifier");
182  		return -1;
183  	}
184  	hdr->identifier = *pos++;
185  	hdr->class = hdr->identifier >> 6;
186  	hdr->constructed = !!(hdr->identifier & (1 << 5));
187  
188  	if ((hdr->identifier & 0x1f) == 0x1f) {
189  		size_t ext_len = 0;
190  
191  		hdr->tag = 0;
192  		if (pos == end || (*pos & 0x7f) == 0) {
193  			wpa_printf(MSG_DEBUG,
194  				   "ASN.1: Invalid extended tag (first octet has to be included with at least one nonzero bit for the tag value)");
195  			return -1;
196  		}
197  		do {
198  			if (pos >= end) {
199  				wpa_printf(MSG_DEBUG, "ASN.1: Identifier "
200  					   "underflow");
201  				return -1;
202  			}
203  			ext_len++;
204  			tmp = *pos++;
205  			wpa_printf(MSG_MSGDUMP, "ASN.1: Extended tag data: "
206  				   "0x%02x", tmp);
207  			hdr->tag = (hdr->tag << 7) | (tmp & 0x7f);
208  		} while (tmp & 0x80);
209  		wpa_printf(MSG_MSGDUMP, "ASN.1: Extended Tag: 0x%x (len=%zu)",
210  			   hdr->tag, ext_len);
211  		if ((hdr->class != ASN1_CLASS_PRIVATE && hdr->tag < 31) ||
212  		    ext_len * 7 > sizeof(hdr->tag) * 8) {
213  			wpa_printf(MSG_DEBUG,
214  				   "ASN.1: Invalid or unsupported (too large) extended Tag: 0x%x (len=%zu)",
215  				   hdr->tag, ext_len);
216  			return -1;
217  		}
218  	} else
219  		hdr->tag = hdr->identifier & 0x1f;
220  
221  	if (pos >= end) {
222  		wpa_printf(MSG_DEBUG, "ASN.1: No room for Length");
223  		return -1;
224  	}
225  	tmp = *pos++;
226  	if (tmp & 0x80) {
227  		if (tmp == 0xff) {
228  			wpa_printf(MSG_DEBUG, "ASN.1: Reserved length "
229  				   "value 0xff used");
230  			return -1;
231  		}
232  		tmp &= 0x7f; /* number of subsequent octets */
233  		hdr->length = 0;
234  		if (tmp == 0 || pos == end || *pos == 0) {
235  			wpa_printf(MSG_DEBUG,
236  				   "ASN.1: Definite long form of the length does not start with a nonzero value");
237  			return -1;
238  		}
239  		if (tmp > 4) {
240  			wpa_printf(MSG_DEBUG, "ASN.1: Too long length field");
241  			return -1;
242  		}
243  		while (tmp--) {
244  			if (pos >= end) {
245  				wpa_printf(MSG_DEBUG, "ASN.1: Length "
246  					   "underflow");
247  				return -1;
248  			}
249  			hdr->length = (hdr->length << 8) | *pos++;
250  		}
251  		if (hdr->length < 128) {
252  			wpa_printf(MSG_DEBUG,
253  				   "ASN.1: Definite long form of the length used with too short length");
254  			return -1;
255  		}
256  	} else {
257  		/* Short form - length 0..127 in one octet */
258  		hdr->length = tmp;
259  	}
260  
261  	if (end < pos || hdr->length > (unsigned int) (end - pos)) {
262  		wpa_printf(MSG_DEBUG, "ASN.1: Contents underflow");
263  		return -1;
264  	}
265  
266  	hdr->payload = pos;
267  
268  	if (!asn1_valid_der(hdr)) {
269  		asn1_print_hdr(hdr, "ASN.1: Invalid DER encoding: ");
270  		return -1;
271  	}
272  	return 0;
273  }
274  
275  
asn1_print_hdr(const struct asn1_hdr * hdr,const char * title)276  void asn1_print_hdr(const struct asn1_hdr *hdr, const char *title)
277  {
278  	wpa_printf(MSG_DEBUG, "%sclass %d constructed %d tag 0x%x",
279  		   title, hdr->class, hdr->constructed, hdr->tag);
280  }
281  
282  
asn1_unexpected(const struct asn1_hdr * hdr,const char * title)283  void asn1_unexpected(const struct asn1_hdr *hdr, const char *title)
284  {
285  	wpa_printf(MSG_DEBUG, "%s - found class %d constructed %d tag 0x%x",
286  		   title, hdr->class, hdr->constructed, hdr->tag);
287  }
288  
289  
asn1_parse_oid(const u8 * buf,size_t len,struct asn1_oid * oid)290  int asn1_parse_oid(const u8 *buf, size_t len, struct asn1_oid *oid)
291  {
292  	const u8 *pos, *end;
293  	unsigned long val;
294  	u8 tmp;
295  
296  	os_memset(oid, 0, sizeof(*oid));
297  
298  	pos = buf;
299  	end = buf + len;
300  
301  	while (pos < end) {
302  		val = 0;
303  
304  		do {
305  			if (pos >= end)
306  				return -1;
307  			tmp = *pos++;
308  			val = (val << 7) | (tmp & 0x7f);
309  		} while (tmp & 0x80);
310  
311  		if (oid->len >= ASN1_MAX_OID_LEN) {
312  			wpa_printf(MSG_DEBUG, "ASN.1: Too long OID value");
313  			return -1;
314  		}
315  		if (oid->len == 0) {
316  			/*
317  			 * The first octet encodes the first two object
318  			 * identifier components in (X*40) + Y formula.
319  			 * X = 0..2.
320  			 */
321  			oid->oid[0] = val / 40;
322  			if (oid->oid[0] > 2)
323  				oid->oid[0] = 2;
324  			oid->oid[1] = val - oid->oid[0] * 40;
325  			oid->len = 2;
326  		} else
327  			oid->oid[oid->len++] = val;
328  	}
329  
330  	return 0;
331  }
332  
333  
asn1_get_oid(const u8 * buf,size_t len,struct asn1_oid * oid,const u8 ** next)334  int asn1_get_oid(const u8 *buf, size_t len, struct asn1_oid *oid,
335  		 const u8 **next)
336  {
337  	struct asn1_hdr hdr;
338  
339  	if (asn1_get_next(buf, len, &hdr) < 0 || hdr.length == 0 ||
340  	    !asn1_is_oid(&hdr)) {
341  		asn1_unexpected(&hdr, "ASN.1: Expected OID");
342  		return -1;
343  	}
344  
345  	*next = hdr.payload + hdr.length;
346  
347  	return asn1_parse_oid(hdr.payload, hdr.length, oid);
348  }
349  
350  
asn1_oid_to_str(const struct asn1_oid * oid,char * buf,size_t len)351  void asn1_oid_to_str(const struct asn1_oid *oid, char *buf, size_t len)
352  {
353  	char *pos = buf;
354  	size_t i;
355  	int ret;
356  
357  	if (len == 0)
358  		return;
359  
360  	buf[0] = '\0';
361  
362  	for (i = 0; i < oid->len; i++) {
363  		ret = os_snprintf(pos, buf + len - pos,
364  				  "%s%lu",
365  				  i == 0 ? "" : ".", oid->oid[i]);
366  		if (os_snprintf_error(buf + len - pos, ret))
367  			break;
368  		pos += ret;
369  	}
370  	buf[len - 1] = '\0';
371  }
372  
373  
rotate_bits(u8 octet)374  static u8 rotate_bits(u8 octet)
375  {
376  	int i;
377  	u8 res;
378  
379  	res = 0;
380  	for (i = 0; i < 8; i++) {
381  		res <<= 1;
382  		if (octet & 1)
383  			res |= 1;
384  		octet >>= 1;
385  	}
386  
387  	return res;
388  }
389  
390  
asn1_bit_string_to_long(const u8 * buf,size_t len)391  unsigned long asn1_bit_string_to_long(const u8 *buf, size_t len)
392  {
393  	unsigned long val = 0;
394  	const u8 *pos = buf;
395  
396  	/* BER requires that unused bits are zero, so we can ignore the number
397  	 * of unused bits */
398  	pos++;
399  
400  	if (len >= 2)
401  		val |= rotate_bits(*pos++);
402  	if (len >= 3)
403  		val |= ((unsigned long) rotate_bits(*pos++)) << 8;
404  	if (len >= 4)
405  		val |= ((unsigned long) rotate_bits(*pos++)) << 16;
406  	if (len >= 5)
407  		val |= ((unsigned long) rotate_bits(*pos++)) << 24;
408  	if (len >= 6)
409  		wpa_printf(MSG_DEBUG, "X509: %s - some bits ignored "
410  			   "(BIT STRING length %lu)",
411  			   __func__, (unsigned long) len);
412  
413  	return val;
414  }
415  
416  
asn1_oid_equal(const struct asn1_oid * a,const struct asn1_oid * b)417  int asn1_oid_equal(const struct asn1_oid *a, const struct asn1_oid *b)
418  {
419  	size_t i;
420  
421  	if (a->len != b->len)
422  		return 0;
423  
424  	for (i = 0; i < a->len; i++) {
425  		if (a->oid[i] != b->oid[i])
426  			return 0;
427  	}
428  
429  	return 1;
430  }
431  
432  
asn1_get_integer(const u8 * buf,size_t len,int * integer,const u8 ** next)433  int asn1_get_integer(const u8 *buf, size_t len, int *integer, const u8 **next)
434  {
435  	struct asn1_hdr hdr;
436  	size_t left;
437  	const u8 *pos;
438  	int value;
439  
440  	if (asn1_get_next(buf, len, &hdr) < 0 || hdr.length == 0 ||
441  	    !asn1_is_integer(&hdr)) {
442  		asn1_unexpected(&hdr, "ASN.1: Expected INTEGER");
443  		return -1;
444  	}
445  
446  	*next = hdr.payload + hdr.length;
447  	pos = hdr.payload;
448  	left = hdr.length;
449  	if (left > sizeof(value)) {
450  		wpa_printf(MSG_DEBUG, "ASN.1: Too large INTEGER (len %u)",
451  			   hdr.length);
452  		return -1;
453  	}
454  	value = 0;
455  	while (left) {
456  		value <<= 8;
457  		value |= *pos++;
458  		left--;
459  	}
460  
461  	*integer = value;
462  	return 0;
463  }
464  
465  
asn1_get_sequence(const u8 * buf,size_t len,struct asn1_hdr * hdr,const u8 ** next)466  int asn1_get_sequence(const u8 *buf, size_t len, struct asn1_hdr *hdr,
467  		      const u8 **next)
468  {
469  	if (asn1_get_next(buf, len, hdr) < 0 || !asn1_is_sequence(hdr)) {
470  		asn1_unexpected(hdr, "ASN.1: Expected SEQUENCE");
471  		return -1;
472  	}
473  
474  	if (next)
475  		*next = hdr->payload + hdr->length;
476  	return 0;
477  }
478  
479  
asn1_get_alg_id(const u8 * buf,size_t len,struct asn1_oid * oid,const u8 ** params,size_t * params_len,const u8 ** next)480  int asn1_get_alg_id(const u8 *buf, size_t len, struct asn1_oid *oid,
481  		    const u8 **params, size_t *params_len, const u8 **next)
482  {
483  	const u8 *pos = buf, *end = buf + len;
484  	struct asn1_hdr hdr;
485  
486  	/*
487  	 * AlgorithmIdentifier ::= SEQUENCE {
488  	 *     algorithm            OBJECT IDENTIFIER,
489  	 *     parameters           ANY DEFINED BY algorithm OPTIONAL}
490  	 */
491  	if (asn1_get_sequence(pos, end - pos, &hdr, next) < 0 ||
492  	    asn1_get_oid(hdr.payload, hdr.length, oid, &pos) < 0)
493  		return -1;
494  
495  	if (params && params_len) {
496  		*params = pos;
497  		*params_len = hdr.payload + hdr.length - pos;
498  	}
499  
500  	return 0;
501  }
502  
503  
asn1_put_integer(struct wpabuf * buf,int val)504  void asn1_put_integer(struct wpabuf *buf, int val)
505  {
506  	u8 bin[4];
507  	int zeros;
508  
509  	WPA_PUT_BE32(bin, val);
510  	zeros = 0;
511  	while (zeros < 3 && bin[zeros] == 0)
512  		zeros++;
513  	wpabuf_put_u8(buf, ASN1_TAG_INTEGER);
514  	wpabuf_put_u8(buf, 4 - zeros);
515  	wpabuf_put_data(buf, &bin[zeros], 4 - zeros);
516  }
517  
518  
asn1_put_len(struct wpabuf * buf,size_t len)519  static void asn1_put_len(struct wpabuf *buf, size_t len)
520  {
521  	if (len <= 0x7f) {
522  		wpabuf_put_u8(buf, len);
523  	} else if (len <= 0xff) {
524  		wpabuf_put_u8(buf, 0x80 | 1);
525  		wpabuf_put_u8(buf, len);
526  	} else if (len <= 0xffff) {
527  		wpabuf_put_u8(buf, 0x80 | 2);
528  		wpabuf_put_be16(buf, len);
529  	} else if (len <= 0xffffff) {
530  		wpabuf_put_u8(buf, 0x80 | 3);
531  		wpabuf_put_be24(buf, len);
532  	} else {
533  		wpabuf_put_u8(buf, 0x80 | 4);
534  		wpabuf_put_be32(buf, len);
535  	}
536  }
537  
538  
asn1_put_octet_string(struct wpabuf * buf,const struct wpabuf * val)539  void asn1_put_octet_string(struct wpabuf *buf, const struct wpabuf *val)
540  {
541  	wpabuf_put_u8(buf, ASN1_TAG_OCTETSTRING);
542  	asn1_put_len(buf, wpabuf_len(val));
543  	wpabuf_put_buf(buf, val);
544  }
545  
546  
asn1_put_oid(struct wpabuf * buf,const struct asn1_oid * oid)547  void asn1_put_oid(struct wpabuf *buf, const struct asn1_oid *oid)
548  {
549  	u8 *len;
550  	size_t i;
551  
552  	if (oid->len < 2)
553  		return;
554  	wpabuf_put_u8(buf, ASN1_TAG_OID);
555  	len = wpabuf_put(buf, 1);
556  	wpabuf_put_u8(buf, 40 * oid->oid[0] + oid->oid[1]);
557  	for (i = 2; i < oid->len; i++) {
558  		unsigned long val = oid->oid[i];
559  		u8 bytes[8];
560  		int idx = 0;
561  
562  		while (val) {
563  			bytes[idx] = (idx ? 0x80 : 0x00) | (val & 0x7f);
564  			idx++;
565  			val >>= 7;
566  		}
567  		if (idx == 0) {
568  			bytes[idx] = 0;
569  			idx = 1;
570  		}
571  		while (idx > 0) {
572  			idx--;
573  			wpabuf_put_u8(buf, bytes[idx]);
574  		}
575  	}
576  	*len = (u8 *) wpabuf_put(buf, 0) - len - 1;
577  }
578  
579  
asn1_put_hdr(struct wpabuf * buf,u8 class,int constructed,u8 tag,size_t len)580  void asn1_put_hdr(struct wpabuf *buf, u8 class, int constructed, u8 tag,
581  		  size_t len)
582  {
583  	wpabuf_put_u8(buf, class << 6 | (constructed ? 0x20 : 0x00) | tag);
584  	asn1_put_len(buf, len);
585  }
586  
587  
asn1_put_sequence(struct wpabuf * buf,const struct wpabuf * payload)588  void asn1_put_sequence(struct wpabuf *buf, const struct wpabuf *payload)
589  {
590  	asn1_put_hdr(buf, ASN1_CLASS_UNIVERSAL, 1, ASN1_TAG_SEQUENCE,
591  		     wpabuf_len(payload));
592  	wpabuf_put_buf(buf, payload);
593  }
594  
595  
asn1_put_set(struct wpabuf * buf,const struct wpabuf * payload)596  void asn1_put_set(struct wpabuf *buf, const struct wpabuf *payload)
597  {
598  	asn1_put_hdr(buf, ASN1_CLASS_UNIVERSAL, 1, ASN1_TAG_SET,
599  		     wpabuf_len(payload));
600  	wpabuf_put_buf(buf, payload);
601  }
602  
603  
asn1_put_utf8string(struct wpabuf * buf,const char * val)604  void asn1_put_utf8string(struct wpabuf *buf, const char *val)
605  {
606  	asn1_put_hdr(buf, ASN1_CLASS_UNIVERSAL, 0, ASN1_TAG_UTF8STRING,
607  		     os_strlen(val));
608  	wpabuf_put_str(buf, val);
609  }
610  
611  
asn1_build_alg_id(const struct asn1_oid * oid,const struct wpabuf * params)612  struct wpabuf * asn1_build_alg_id(const struct asn1_oid *oid,
613  				  const struct wpabuf *params)
614  {
615  	struct wpabuf *buf;
616  	size_t len;
617  
618  	/*
619  	 * AlgorithmIdentifier ::= SEQUENCE {
620  	 *    algorithm		OBJECT IDENTIFIER,
621  	 *    parameters	ANY DEFINED BY algorithm OPTIONAL}
622  	 */
623  
624  	len = 100;
625  	if (params)
626  		len += wpabuf_len(params);
627  	buf = wpabuf_alloc(len);
628  	if (!buf)
629  		return NULL;
630  	asn1_put_oid(buf, oid);
631  	if (params)
632  		wpabuf_put_buf(buf, params);
633  	return asn1_encaps(buf, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE);
634  }
635  
636  
asn1_encaps(struct wpabuf * buf,u8 class,u8 tag)637  struct wpabuf * asn1_encaps(struct wpabuf *buf, u8 class, u8 tag)
638  {
639  	struct wpabuf *res;
640  
641  	if (!buf)
642  		return NULL;
643  	res = wpabuf_alloc(10 + wpabuf_len(buf));
644  	if (res) {
645  		asn1_put_hdr(res, class, 1, tag, wpabuf_len(buf));
646  		wpabuf_put_buf(res, buf);
647  	}
648  	wpabuf_clear_free(buf);
649  	return res;
650  }
651