comparison usr/src/cmd/agents/snmp/snmplib/asn1.c @ 0:c9caec207d52 b86

Initial porting based on b86
author Koji Uno <koji.uno@sun.com>
date Tue, 02 Jun 2009 18:56:50 +0900
parents
children 1a15d5aaf794
comparison
equal deleted inserted replaced
-1:000000000000 0:c9caec207d52
1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 2001,2002 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #pragma ident "@(#)asn1.c 1.10 05/06/12 SMI"
28
29 #include <string.h>
30 #include <stdio.h>
31 #include <sys/types.h>
32 #include <netinet/in.h>
33 #include "snmp_msg.h"
34 #include "asn1.h"
35
36
37 /*
38 * asn_parse_int - pulls a int32_t out of an ASN int type.
39 * On entry, datalength is input as the number of valid bytes following
40 * "data". On exit, it is returned as the number of valid bytes
41 * following the end of this object.
42 *
43 * Returns a pointer to the first byte past the end
44 * of this object (i.e. the start of the next object).
45 * Returns NULL on any error.
46 */
47 u_char *
48 asn_parse_int(
49 u_char *data, /* IN - pointer to start of object */
50 uint32_t *datalength,/* IN/OUT - number of valid bytes left in buffer */
51 u_char *type, /* OUT - asn type of object */
52 int32_t *intp, /* IN/OUT - pointer to start of output buffer */
53 uint32_t intsize, /* IN - size of output buffer */
54 char *error_label)
55 {
56 /*
57 * ASN.1 integer ::= 0x02 asnlength byte {byte}*
58 */
59 u_char *bufp = data;
60 uint32_t asn_length = 0;
61 int32_t value = 0;
62
63
64 error_label[0] = '\0';
65
66 if (intsize != sizeof (int32_t)){
67 (void)sprintf(error_label, ERR_MSG_NOT_LONG);
68 return NULL;
69 }
70 *type = *bufp++;
71 bufp = asn_parse_length(bufp, &asn_length, error_label);
72 if (bufp == NULL){
73 (void)sprintf(error_label, ERR_MSG_BAD_LENGTH);
74 return NULL;
75 }
76 /* LINTED */
77 if (asn_length + (uint32_t)(bufp - data) > *datalength){
78 (void)sprintf(error_label, ERR_MSG_OVERFLOW);
79 return NULL;
80 }
81 if (asn_length > intsize){
82 (void)sprintf(error_label, ERR_MSG_DONT_SUPPORT_LARGE_INT);
83 return NULL;
84 }
85 /* LINTED */
86 *datalength -= asn_length + (uint32_t)(bufp - data);
87 if (*bufp & 0x80)
88 value = -1; /* integer is negative */
89 while(asn_length--)
90 value = (value << 8) | *bufp++;
91 *intp = value;
92 return bufp;
93 }
94
95 /*
96 * asn_parse_unsigned_int - pulls an unsigned int32_t out of an ASN int type.
97 * On entry, datalength is input as the number of valid bytes following
98 * "data". On exit, it is returned as the number of valid bytes
99 * following the end of this object.
100 *
101 * Returns a pointer to the first byte past the end
102 * of this object (i.e. the start of the next object).
103 * Returns NULL on any error.
104 */
105 u_char *
106 asn_parse_unsigned_int(
107 u_char *data, /* IN - pointer to start of object */
108 uint32_t * datalength,/* IN/OUT - number of valid bytes left in buffer */
109 u_char *type, /* OUT - asn type of object */
110 int32_t *intp, /* IN/OUT - pointer to start of output buffer */
111 uint32_t intsize, /* IN - size of output buffer */
112 char *error_label)
113 {
114 /*
115 * ASN.1 integer ::= 0x02 asnlength byte {byte}*
116 */
117 u_char *bufp = data;
118 uint32_t asn_length;
119 uint32_t value = 0;
120
121 error_label[0] = '\0';
122
123 if (intsize != sizeof (int32_t)){
124 (void)sprintf(error_label, ERR_MSG_NOT_LONG);
125 return NULL;
126 }
127 *type = *bufp++;
128 bufp = asn_parse_length(bufp, &asn_length, error_label);
129 if (bufp == NULL){
130 (void)sprintf(error_label, ERR_MSG_BAD_LENGTH);
131 return NULL;
132 }
133 /* LINTED */
134 if (asn_length + (uint32_t)(bufp - data) > *datalength){
135 (void)sprintf(error_label, ERR_MSG_OVERFLOW);
136 return NULL;
137 }
138 if ((asn_length > (intsize + 1)) ||
139 ((asn_length == intsize + 1) && *bufp != 0x00)){
140 (void)sprintf(error_label, ERR_MSG_DONT_SUPPORT_LARGE_INT);
141 return NULL;
142 }
143 /* LINTED */
144 *datalength -= asn_length + (uint32_t)(bufp - data);
145 if (*bufp & 0x80)
146 value = -1U; /* integer is negative */
147 while(asn_length--)
148 value = (value << 8) | *bufp++;
149 *intp = value;
150 return bufp;
151 }
152
153
154 /*
155 * asn_build_int - builds an ASN object containing an integer.
156 * On entry, datalength is input as the number of valid bytes following
157 * "data". On exit, it is returned as the number of valid bytes
158 * following the end of this object.
159 *
160 * Returns a pointer to the first byte past the end
161 * of this object (i.e. the start of the next object).
162 * Returns NULL on any error.
163 */
164 u_char *
165 asn_build_int(
166 u_char *data, /* IN - pointer to start of output buffer */
167 uint32_t * datalength,/* IN/OUT - number of valid bytes left in buffer */
168 u_char type, /* IN - asn type of object */
169 int32_t *intp, /* IN - pointer to start of integer */
170 uint32_t intsize, /* IN - size of *intp */
171 char *error_label)
172 {
173 /*
174 * ASN.1 integer ::= 0x02 asnlength byte {byte}*
175 */
176
177 int32_t integer;
178 uint32_t mask;
179
180 error_label[0] = '\0';
181
182 if (intsize != sizeof (int32_t))
183 return NULL;
184 integer = *intp;
185 /*
186 * Truncate "unnecessary" bytes off of the most significant end of this 2's
187 * complement integer. There should be no sequence of 9 consecutive 1's or
188 * 0's at the most significant end of the integer.
189 */
190 mask = ((uint32_t) 0x1FF) << ((8 * (sizeof(int32_t) - 1)) - 1);
191
192 /* mask is 0xFF800000 on a big-endian machine */
193 while((((integer & mask) == 0) || ((integer & mask) == mask)) && intsize > 1){
194 intsize--;
195 integer <<= 8;
196 }
197 data = asn_build_header(data, datalength, type, intsize, error_label);
198 if (data == NULL)
199 return NULL;
200 if (*datalength < intsize)
201 return NULL;
202 *datalength -= intsize;
203
204 mask = ((uint32_t) 0xFF) << (8 * (sizeof(int32_t) - 1));
205
206 /* mask is 0xFF000000 on a big-endian machine */
207 while(intsize--){
208 /* LINTED */
209 *data++ = (u_char)((integer & mask) >> (8 * (sizeof(int32_t) - 1)));
210 integer <<= 8;
211 }
212 return data;
213 }
214
215 /*
216 * asn_build_unsigned_int - builds an ASN object containing an integer.
217 * On entry, datalength is input as the number of valid bytes following
218 * "data". On exit, it is returned as the number of valid bytes
219 * following the end of this object.
220 *
221 * Returns a pointer to the first byte past the end
222 * of this object (i.e. the start of the next object).
223 * Returns NULL on any error.
224 */
225 u_char *
226 asn_build_unsigned_int(
227 u_char *data, /* IN - pointer to start of output buffer */
228 uint32_t *datalength,/* IN/OUT - number of valid bytes left in buffer */
229 u_char type, /* IN - asn type of object */
230 int32_t *intp, /* IN - pointer to start of int32_t integer */
231 uint32_t intsize, /* IN - size of *intp */
232 char *error_label)
233 {
234 /*
235 * ASN.1 integer ::= 0x02 asnlength byte {byte}*
236 */
237
238 uint32_t integer;
239 uint32_t mask;
240 int add_null_byte = 0;
241
242 error_label[0] = '\0';
243
244 if (intsize != sizeof (int32_t))
245 return NULL;
246 integer = *intp;
247 mask = ((uint32_t) 0xFF) << (8 * (sizeof(int32_t) - 1));
248 /* mask is 0xFF000000 on a big-endian machine */
249 /* LINTED */
250 if ((u_char)((integer & mask) >> (8 * (sizeof(int32_t) - 1))) & 0x80){
251 /* if MSB is set */
252 add_null_byte = 1;
253 intsize++;
254 } else {
255 /*
256 * Truncate "unnecessary" bytes off of the most significant end of this 2's complement integer.
257 * There should be no sequence of 9 consecutive 1's or 0's at the most significant end of the
258 * integer.
259 */
260 mask = ((uint32_t) 0x1FF) << ((8 * (sizeof(int32_t) - 1)) - 1);
261 /* mask is 0xFF800000 on a big-endian machine */
262 while(((integer & mask) == 0) && intsize > 1){
263 intsize--;
264 integer <<= 8;
265 }
266 }
267 data = asn_build_header(data, datalength, type, intsize, error_label);
268 if (data == NULL)
269 return NULL;
270 if (*datalength < intsize)
271 return NULL;
272 *datalength -= intsize;
273 if (add_null_byte == 1){
274 *data++ = '\0';
275 intsize--;
276 }
277 mask = ((uint32_t) 0xFF) << (8 * (sizeof(int32_t) - 1));
278 /* mask is 0xFF000000 on a big-endian machine */
279 while(intsize--){
280 /* LINTED */
281 *data++ = (u_char)((integer & mask) >> (8 * (sizeof(int32_t) - 1)));
282 integer <<= 8;
283 }
284 return data;
285 }
286
287
288 /*
289 * asn_parse_string - pulls an octet string out of an ASN octet string type.
290 * On entry, datalength is input as the number of valid bytes following
291 * "data". On exit, it is returned as the number of valid bytes
292 * following the beginning of the next object.
293 *
294 * "string" is filled with the octet string.
295 *
296 * Returns a pointer to the first byte past the end
297 * of this object (i.e. the start of the next object).
298 * Returns NULL on any error.
299 */
300 u_char *
301 asn_parse_string(
302 u_char *data, /* IN - pointer to start of object */
303 uint32_t *datalength, /* IN/OUT - number of valid bytes left in buffer */
304 u_char *type, /* OUT - asn type of object */
305 u_char *string, /* IN/OUT - pointer to start of output buffer */
306 uint32_t *strlength, /* IN/OUT - size of output buffer */
307 char *error_label)
308 {
309 /*
310 * ASN.1 octet string ::= primstring | cmpdstring
311 * primstring ::= 0x04 asnlength byte {byte}*
312 * cmpdstring ::= 0x24 asnlength string {string}*
313 * This doesn't yet support the compound string.
314 */
315 u_char *bufp = data;
316 uint32_t asn_length = 0;
317
318
319 error_label[0] = '\0';
320
321 *type = *bufp++;
322 bufp = asn_parse_length(bufp, &asn_length, error_label);
323 if (bufp == NULL)
324 return NULL;
325 /* LINTED */
326 if (asn_length + (uint32_t)(bufp - data) > *datalength){
327 (void)sprintf(error_label, ERR_MSG_OVERFLOW);
328 return NULL;
329 }
330 if (asn_length > *strlength){
331 (void)sprintf(error_label, ERR_MSG_DONT_SUPPORT_LARGE_STR);
332 return NULL;
333 }
334 memcpy(string, bufp, asn_length);
335 *strlength = asn_length;
336 /* LINTED */
337 *datalength -= asn_length + (uint32_t)(bufp - data);
338 return bufp + asn_length;
339 }
340
341
342 /*
343 * asn_build_string - Builds an ASN octet string object containing the input string.
344 * On entry, datalength is input as the number of valid bytes following
345 * "data". On exit, it is returned as the number of valid bytes
346 * following the beginning of the next object.
347 *
348 * Returns a pointer to the first byte past the end
349 * of this object (i.e. the start of the next object).
350 * Returns NULL on any error.
351 */
352 u_char *
353 asn_build_string(
354 u_char *data, /* IN - pointer to start of object */
355 uint32_t *datalength, /* IN/OUT - number of valid bytes left in buffer */
356 u_char type, /* IN - ASN type of string */
357 u_char *string, /* IN - pointer to start of input buffer */
358 uint32_t strlength, /* IN - size of input buffer */
359 char *error_label)
360 {
361 /*
362 * ASN.1 octet string ::= primstring | cmpdstring
363 * primstring ::= 0x04 asnlength byte {byte}*
364 * cmpdstring ::= 0x24 asnlength string {string}*
365 * This code will never send a compound string.
366 */
367
368 error_label[0] = '\0';
369
370 data = asn_build_header(data, datalength, type, strlength, error_label);
371 if (data == NULL)
372 return NULL;
373 if (*datalength < strlength)
374 return NULL;
375 memcpy(data, string, strlength);
376 *datalength -= strlength;
377 return data + (intptr_t)strlength;
378 }
379
380
381 /*
382 * asn_parse_header - interprets the ID and length of the current object.
383 * On entry, datalength is input as the number of valid bytes following
384 * "data". On exit, it is returned as the number of valid bytes
385 * in this object following the id and length.
386 *
387 * Returns a pointer to the first byte of the contents of this object.
388 * Returns NULL on any error.
389 */
390 u_char *
391 asn_parse_header(
392 u_char *data, /* IN - pointer to start of object */
393 uint32_t * datalength,/* IN/OUT - number of valid bytes left in buffer */
394 u_char *type, /* OUT - ASN type of object */
395 char *error_label)
396 {
397 u_char *bufp = data;
398 uint32_t header_len;
399 uint32_t asn_length = 0;
400
401 error_label[0] = '\0';
402
403 /* this only works on data types < 30, i.e. no extension octets */
404 if (IS_EXTENSION_ID(*bufp)){
405 (void)sprintf(error_label, ERR_MSG_CANT_PROCESS_LONG_ID);
406 return NULL;
407 }
408 *type = *bufp;
409 bufp = asn_parse_length(bufp + 1, &asn_length, error_label);
410 if (bufp == NULL)
411 return NULL;
412
413 /* LINTED */
414 header_len = (uint32_t)(bufp - data);
415 if (header_len + asn_length > *datalength){
416 (void)sprintf(error_label, ERR_MSG_ASN_LEN_TOO_LONG);
417 return NULL;
418 }
419 *datalength = asn_length;
420 return bufp;
421 }
422
423 /*
424 * asn_build_header - builds an ASN header for an object with the ID and
425 * length specified.
426 * On entry, datalength is input as the number of valid bytes following
427 * "data". On exit, it is returned as the number of valid bytes
428 * in this object following the id and length.
429 *
430 * This only works on data types < 30, i.e. no extension octets.
431 * The maximum length is 0xFFFF;
432 *
433 * Returns a pointer to the first byte of the contents of this object.
434 * Returns NULL on any error.
435 */
436 u_char *
437 asn_build_header(
438 u_char *data, /* IN - pointer to start of object */
439 uint32_t *datalength,/* IN/OUT - number of valid bytes left in buffer */
440 u_char type, /* IN - ASN type of object */
441 uint32_t length, /* IN - length of object */
442 char *error_label)
443 {
444 error_label[0] = '\0';
445
446 if (*datalength == 0)
447 return NULL;
448 *data++ = type;
449 (*datalength)--;
450 return asn_build_length(data, datalength, length, error_label);
451
452 }
453
454 /*
455 * asn_parse_length - interprets the length of the current object.
456 * On exit, length contains the value of this length field.
457 *
458 * Returns a pointer to the first byte after this length
459 * field (aka: the start of the data field).
460 * Returns NULL on any error.
461 */
462 u_char *
463 asn_parse_length(
464 u_char *data, /* IN - pointer to start of length field */
465 uint32_t *length, /* OUT - value of length field */
466 char *error_label)
467 {
468 u_char lengthbyte = *data;
469
470 error_label[0] = '\0';
471
472 if (lengthbyte & ASN_LONG_LEN){
473 lengthbyte &= ~ASN_LONG_LEN; /* turn MSb off */
474 if (lengthbyte == 0){
475 (void)sprintf(error_label, ERR_MSG_DONT_SUPPORT_INDEF_LEN);
476 return NULL;
477 }
478 if (lengthbyte > sizeof(int32_t)){
479 (void)sprintf(error_label, ERR_MSG_DONT_SUPPORT_SUCH_LEN);
480 return NULL;
481 }
482 memcpy(length, data + 1, (int)lengthbyte);
483 *length = ntohl(*length);
484 *length >>= (8 * ((sizeof *length) - lengthbyte));
485 return data + lengthbyte + 1;
486 } else { /* short asnlength */
487 *length = (int32_t)lengthbyte;
488 return data + 1;
489 }
490 }
491
492 u_char *
493 asn_build_length(
494 u_char *data, /* IN - pointer to start of object */
495 uint32_t *datalength, /* IN/OUT - number of valid bytes left in buffer */
496 uint32_t length, /* IN - length of object */
497 char *error_label)
498 {
499 u_char *start_data = data;
500
501 error_label[0] = '\0';
502
503 /* no indefinite lengths sent */
504 if (length < 0x80){
505 if (*datalength < 1)
506 goto errout;
507 /* LINTED */
508 *data++ = (u_char)length;
509 } else if (length <= 0xFF){
510 if (*datalength < 2)
511 goto errout;
512 /* LINTED */
513 *data++ = (u_char)(0x01 | ASN_LONG_LEN);
514 /* LINTED */
515 *data++ = (u_char)length;
516 } else { /* 0xFF < length <= 0xFFFF */
517 if (*datalength < 3)
518 goto errout;
519 /* LINTED */
520 *data++ = (u_char)(0x02 | ASN_LONG_LEN);
521 /* LINTED */
522 *data++ = (u_char)((length >> 8) & 0xFF);
523 /* LINTED */
524 *data++ = (u_char)(length & 0xFF);
525 }
526 /* LINTED */
527 *datalength -= (uint32_t)(data - start_data);
528 return data;
529
530 errout:
531 (void)sprintf(error_label, ERR_MSG_BUILD_LENGTH);
532 return NULL;
533 }
534
535 /*
536 * asn_parse_objid - pulls an object indentifier out of an ASN object identifier type.
537 * On entry, datalength is input as the number of valid bytes following
538 * "data". On exit, it is returned as the number of valid bytes
539 * following the beginning of the next object.
540 *
541 * "objid" is filled with the object identifier.
542 *
543 * Returns a pointer to the first byte past the end
544 * of this object (i.e. the start of the next object).
545 * Returns NULL on any error.
546 */
547 u_char *
548 asn_parse_objid(
549 u_char *data, /* IN - pointer to start of object */
550 uint32_t *datalength, /* IN/OUT - number of valid bytes left in buffer */
551 u_char *type, /* OUT - ASN type of object */
552 Subid *objid, /* IN/OUT - pointer to start of output buffer */
553 int32_t *objidlength, /* IN/OUT - number of sub-id's in objid */
554 char *error_label)
555 {
556 /*
557 * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}*
558 * subidentifier ::= {leadingbyte}* lastbyte
559 * leadingbyte ::= 1 7bitvalue
560 * lastbyte ::= 0 7bitvalue
561 */
562 u_char *bufp = data;
563 Subid *oidp = objid + 1;
564 uint32_t subidentifier;
565 int32_t length;
566 uint32_t asn_length = 0;
567
568
569 error_label[0] = '\0';
570
571 *type = *bufp++;
572 bufp = asn_parse_length(bufp, &asn_length, error_label);
573 if (bufp == NULL)
574 return NULL;
575 /* LINTED */
576 if (asn_length + (uint32_t)(bufp - data) > *datalength){
577 (void)sprintf(error_label, ERR_MSG_OVERFLOW);
578 return NULL;
579 }
580 /* LINTED */
581 *datalength -= asn_length + (uint32_t)(bufp - data);
582
583 length = asn_length;
584 (*objidlength)--; /* account for expansion of first byte */
585 while (length > 0 && (*objidlength)-- > 0){
586 subidentifier = 0;
587 do { /* shift and add in low order 7 bits */
588 subidentifier = (subidentifier << 7) + (*(u_char *)bufp & ~ASN_BIT8);
589 length--;
590 } while (*(u_char *)bufp++ & ASN_BIT8); /* last byte has high bit clear */
591 if (subidentifier > (uint32_t)MAX_SUBID){
592 (void)sprintf(error_label, ERR_MSG_SUBIDENTIFIER_TOO_LONG);
593 return NULL;
594 }
595 *oidp++ = (Subid)subidentifier;
596 }
597
598 /*
599 * The first two subidentifiers are encoded into the first component
600 * with the value (X * 40) + Y, where:
601 * X is the value of the first subidentifier.
602 * Y is the value of the second subidentifier.
603 */
604 subidentifier = (uint32_t)objid[1];
605 /* LINTED */
606 objid[1] = (u_char)(subidentifier % 0x28);
607 /* LINTED */
608 objid[0] = (u_char)((subidentifier - objid[1]) / 0x28);
609
610 /* LINTED */
611 *objidlength = (int32_t)(oidp - objid);
612 return bufp;
613 }
614
615 /*
616 * asn_build_objid - Builds an ASN object identifier object containing the input string.
617 * On entry, datalength is input as the number of valid bytes following
618 * "data". On exit, it is returned as the number of valid bytes
619 * following the beginning of the next object.
620 *
621 * Returns a pointer to the first byte past the end
622 * of this object (i.e. the start of the next object).
623 * Returns NULL on any error.
624 */
625 u_char *
626 asn_build_objid(
627 u_char *data, /* IN - pointer to start of object */
628 uint32_t *datalength, /* IN/OUT - number of valid bytes left in buffer */
629 u_char type, /* IN - ASN type of object */
630 Subid *objid, /* IN - pointer to start of input buffer */
631 int32_t objidlength, /* IN - number of sub-id's in objid */
632 char *error_label)
633 {
634 /*
635 * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}*
636 * subidentifier ::= {leadingbyte}* lastbyte
637 * leadingbyte ::= 1 7bitvalue
638 * lastbyte ::= 0 7bitvalue
639 */
640
641 uchar_t buf[MAX_OID_LEN * 5];
642 uchar_t *bp = buf;
643 Subid objbuf[MAX_OID_LEN];
644 Subid *op = objbuf;
645 uint32_t asnlength;
646 uint32_t subid, mask, testmask;
647 int bits, testbits;
648
649 error_label[0] = '\0';
650
651 if (objidlength > MAX_OID_LEN)
652 return (NULL);
653
654 memcpy(objbuf, objid, objidlength * (int32_t)sizeof (Subid));
655 /* transform size in bytes to size in subid's */
656 /* encode the first two components into the first subidentifier */
657 op[1] = op[1] + (op[0] * 40);
658 op++;
659 objidlength--;
660
661 while (objidlength-- > 0){
662 subid = *op++;
663 mask = 0x7F; /* handle subid == 0 case */
664 bits = 0;
665 /* testmask *MUST* !!!! be of an unsigned type */
666 for (testmask = 0x7F, testbits = 0; testmask != 0;
667 testmask <<= 7, testbits += 7) {
668 if (subid & testmask) { /* if any bits set */
669 mask = testmask;
670 bits = testbits;
671 }
672 }
673 /* mask can't be zero here */
674 for (; mask != 0x7F; mask >>= 7, bits -= 7){
675 if (mask == 0x1E00000)
676 /* fix a mask that got truncated above */
677 mask = 0xFE00000;
678 /* LINTED */
679 *bp++ = (uchar_t)(((subid & mask) >> bits) | ASN_BIT8);
680 }
681 /* LINTED */
682 *bp++ = (uchar_t)(subid & mask);
683 }
684 /* LINTED */
685 asnlength = (uint32_t)(bp - buf);
686 data = asn_build_header(data, datalength, type, asnlength, error_label);
687 if (data == NULL)
688 return (NULL);
689 if (*datalength < asnlength)
690 return (NULL);
691 memcpy(data, buf, asnlength);
692 *datalength -= asnlength;
693 return (data + (uintptr_t)asnlength);
694 }
695
696 /*
697 * asn_parse_null - Interprets an ASN null type.
698 * On entry, datalength is input as the number of valid bytes following
699 * "data". On exit, it is returned as the number of valid bytes
700 * following the beginning of the next object.
701 *
702 * Returns a pointer to the first byte past the end
703 * of this object (i.e. the start of the next object).
704 * Returns NULL on any error.
705 */
706 u_char *
707 asn_parse_null(
708 u_char *data, /* IN - pointer to start of object */
709 uint32_t *datalength, /* IN/OUT - number of valid bytes left in buffer */
710 u_char *type, /* OUT - ASN type of object */
711 char *error_label)
712 {
713 /*
714 * ASN.1 null ::= 0x05 0x00
715 */
716 u_char *bufp = data;
717 uint32_t asn_length = 0;
718
719
720 error_label[0] = '\0';
721
722 *type = *bufp++;
723 bufp = asn_parse_length(bufp, &asn_length, error_label);
724 if (bufp == NULL)
725 return NULL;
726 if (asn_length != 0){
727 (void)sprintf(error_label, ERR_MSG_MALFORMED_NULL);
728 return NULL;
729 }
730 /* LINTED */
731 *datalength -= (uint32_t)(bufp - data);
732 return bufp + (uintptr_t)asn_length;
733 }
734
735 /*
736 * asn_build_null - Builds an ASN null object.
737 * On entry, datalength is input as the number of valid bytes following
738 * "data". On exit, it is returned as the number of valid bytes
739 * following the beginning of the next object.
740 *
741 * Returns a pointer to the first byte past the end
742 * of this object (i.e. the start of the next object).
743 * Returns NULL on any error.
744 */
745 u_char *
746 asn_build_null(
747 u_char *data, /* IN - pointer to start of object */
748 uint32_t *datalength, /* IN/OUT - number of valid bytes left in buffer */
749 u_char type, /* IN - ASN type of object */
750 char *error_label)
751 {
752 /*
753 * ASN.1 null ::= 0x05 0x00
754 */
755 error_label[0] = '\0';
756
757 return asn_build_header(data, datalength, type, 0, error_label);
758 }