Annotation of embedaddon/libnet/src/libnet_asn1.c, revision 1.1.1.2
1.1 misho 1: /*
2: * $Id: libnet_asn1.c,v 1.5 2004/01/03 20:31:01 mike Exp $
3: *
4: * libnet 1.1
5: * libnet_asn1.c - Abstract Syntax Notation One routines
6: *
7: * Abstract Syntax Notation One, ASN.1
8: * As defined in ISO/IS 8824 and ISO/IS 8825
9: * This implements a subset of the above International Standards that
10: * is sufficient to implement SNMP.
11: *
12: * Encodes abstract data types into a machine independent stream of bytes.
13: *
14: * Copyright 1988, 1989, 1991, 1992 by Carnegie Mellon University
15: * All rights reserved.
16: *
17: * Permission to use, copy, modify, and distribute this software and its
18: * documentation for any purpose and without fee is hereby granted,
19: * provided that the above copyright notice appear in all copies and that
20: * both that copyright notice and this permission notice appear in
21: * supporting documentation, and that the name of CMU not be
22: * used in advertising or publicity pertaining to distribution of the
23: * software without specific, written prior permission.
24: *
25: * CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
26: * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
27: * CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
28: * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
29: * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
30: * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
31: * SOFTWARE.
32: *
33: * Copyright (c) 1998 - 2004 Mike D. Schiffman <mike@infonexus.com>
34: * All rights reserved.
35: *
36: * Copyright (c) 1993, 1994, 1995, 1996, 1998
37: * The Regents of the University of California. All rights reserved.
38: *
39: * Redistribution and use in source and binary forms, with or without
40: * modification, are permitted provided that: (1) source code distributions
41: * retain the above copyright notice and this paragraph in its entirety, (2)
42: * distributions including binary code include the above copyright notice and
43: * this paragraph in its entirety in the documentation or other materials
44: * provided with the distribution, and (3) all advertising materials mentioning
45: * features or use of this software display the following acknowledgement:
46: * ``This product includes software developed by the University of California,
47: * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
48: * the University nor the names of its contributors may be used to endorse
49: * or promote products derived from this software without specific prior
50: * written permission.
51: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
52: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
53: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
54: */
55:
56: #if (HAVE_CONFIG_H)
57: #include "../include/config.h"
58: #endif
59: #if (!(_WIN32) || (__CYGWIN__))
60: #include "../include/libnet.h"
61: #else
62: #include "../include/win32/libnet.h"
63: #endif
64:
1.1.1.2 ! misho 65: uint8_t *
! 66: libnet_build_asn1_int(uint8_t *data, int *datalen, uint8_t type, int32_t *int_p,
1.1 misho 67: int int_s)
68: {
69: /*
70: * ASN.1 integer ::= 0x02 asnlength byte {byte}*
71: */
72: register int32_t integer;
1.1.1.2 ! misho 73: register uint32_t mask;
1.1 misho 74:
75: if (int_s != sizeof (int32_t))
76: {
77: return (NULL);
78: }
79: integer = *int_p;
80:
81: /*
82: * Truncate "unnecessary" bytes off of the most significant end of this
83: * 2's complement integer. There should be no sequence of 9 consecutive
84: * 1's or 0's at the most significant end of the integer.
85: */
1.1.1.2 ! misho 86: mask = ((uint32_t) 0x1FF) << ((8 * (sizeof (int32_t) - 1)) - 1);
1.1 misho 87: /* mask is 0xFF800000 on a big-endian machine */
88:
89: while ((((integer & mask) == 0) || ((integer & mask) == mask)) && int_s > 1)
90: {
91: int_s--;
92: integer <<= 8;
93: }
94:
95: data = libnet_build_asn1_header(data, datalen, type, int_s);
96:
97: if (data == NULL || *datalen < int_s)
98: {
99: return (NULL);
100: }
101:
102: *datalen -= int_s;
103:
1.1.1.2 ! misho 104: mask = ((uint32_t) 0xFF) << (8 * (sizeof(int32_t) - 1));
1.1 misho 105: /* mask is 0xFF000000 on a big-endian machine */
106:
107: while (int_s--)
108: {
1.1.1.2 ! misho 109: *data++ = (uint8_t)((integer & mask) >> (8 * (sizeof (int32_t) - 1)));
1.1 misho 110: integer <<= 8;
111: }
112: return (data);
113: }
114:
115:
1.1.1.2 ! misho 116: uint8_t *
! 117: libnet_build_asn1_uint(uint8_t *data, int *datalen, uint8_t type, uint32_t *int_p,
1.1 misho 118: int int_s)
119: {
120: /*
121: * ASN.1 integer ::= 0x02 asnlength byte {byte}*
122: */
1.1.1.2 ! misho 123: register uint32_t integer;
! 124: register uint32_t mask;
1.1 misho 125: int add_null_byte = 0;
126:
127: if (int_s != sizeof (int32_t))
128: {
129: return (NULL);
130: }
131: integer = *int_p;
132:
1.1.1.2 ! misho 133: mask = ((uint32_t) 0xFF) << (8 * (sizeof (int32_t) - 1));
1.1 misho 134: /* mask is 0xFF000000 on a big-endian machine */
135:
1.1.1.2 ! misho 136: if ((uint8_t)((integer & mask) >> (8 * (sizeof (int32_t) - 1))) & 0x80)
1.1 misho 137: {
138: /* if MSB is set */
139: add_null_byte = 1;
140: int_s++;
141: }
142: else
143: {
144: /*
145: * Truncate "unnecessary" bytes off of the most significant end of this
146: * 2's complement integer. There should be no sequence of 9
147: * consecutive 1's or 0's at the most significant end of the
148: * integer.
149: */
1.1.1.2 ! misho 150: mask = ((uint32_t) 0x1FF) << ((8 * (sizeof(int32_t) - 1)) - 1);
1.1 misho 151: /* mask is 0xFF800000 on a big-endian machine */
152:
153: while (((integer & mask) == 0) && int_s > 1)
154: {
155: int_s--;
156: integer <<= 8;
157: }
158: }
159:
160: data = libnet_build_asn1_header(data, datalen, type, int_s);
161:
162: if (data == NULL || *datalen < int_s)
163: {
164: return (NULL);
165: }
166:
167: *datalen -= int_s;
168:
169: if (add_null_byte == 1)
170: {
171: *data++ = '\0';
172: int_s--;
173: }
174:
1.1.1.2 ! misho 175: mask = ((uint32_t) 0xFF) << (8 * (sizeof(int32_t) - 1));
1.1 misho 176: /* mask is 0xFF000000 on a big-endian machine */
177:
178: while (int_s--)
179: {
1.1.1.2 ! misho 180: *data++ = (uint8_t)((integer & mask) >> (8 * (sizeof (int32_t) - 1)));
1.1 misho 181: integer <<= 8;
182: }
183: return (data);
184: }
185:
186:
1.1.1.2 ! misho 187: uint8_t *
! 188: libnet_build_asn1_string(uint8_t *data, int *datalen, uint8_t type,
! 189: uint8_t *string, int str_s)
1.1 misho 190: {
191:
192: /*
193: * ASN.1 octet string ::= primstring | cmpdstring
194: * primstring ::= 0x04 asnlength byte {byte}*
195: * cmpdstring ::= 0x24 asnlength string {string}*
196: * This code will never send a compound string.
197: */
198: data = libnet_build_asn1_header(data, datalen, type, str_s);
199:
200: if (data == NULL || *datalen < str_s)
201: {
202: return (NULL);
203: }
204: memmove(data, string, str_s);
205: *datalen -= str_s;
206:
207: return (data + str_s);
208: }
209:
210:
1.1.1.2 ! misho 211: uint8_t *
! 212: libnet_build_asn1_header(uint8_t *data, int *datalen, uint8_t type, int len)
1.1 misho 213: {
214: if (*datalen < 1)
215: {
216: return (NULL);
217: }
218: *data++ = type;
219: (*datalen)--;
220:
221: return (libnet_build_asn1_length(data, datalen, len));
222: }
223:
224:
1.1.1.2 ! misho 225: uint8_t *
! 226: libnet_build_asn1_sequence(uint8_t *data, int *datalen, uint8_t type, int len)
1.1 misho 227: {
228: *datalen -= 4;
229: if (*datalen < 0)
230: {
231: *datalen += 4; /* fix up before punting */
232: return (NULL);
233: }
234: *data++ = type;
1.1.1.2 ! misho 235: *data++ = (uint8_t)(0x02 | ASN_LONG_LEN);
! 236: *data++ = (uint8_t)((len >> 8) & 0xFF);
! 237: *data++ = (uint8_t)(len & 0xFF);
1.1 misho 238: return (data);
239: }
240:
241:
1.1.1.2 ! misho 242: uint8_t *
! 243: libnet_build_asn1_length(uint8_t *data, int *datalen, int len)
1.1 misho 244: {
1.1.1.2 ! misho 245: uint8_t *start_data = data;
1.1 misho 246:
247: /* no indefinite lengths sent */
248: if (len < 0x80)
249: {
250: if (*datalen < 1)
251: {
252: return (NULL);
253: }
1.1.1.2 ! misho 254: *data++ = (uint8_t)len;
1.1 misho 255: }
256: else if (len <= 0xFF)
257: {
258: if (*datalen < 2)
259: {
260: return (NULL);
261: }
1.1.1.2 ! misho 262: *data++ = (uint8_t)(0x01 | ASN_LONG_LEN);
! 263: *data++ = (uint8_t)len;
1.1 misho 264: }
265: else /* 0xFF < len <= 0xFFFF */
266: {
267: if (*datalen < 3)
268: {
269: return (NULL);
270: }
1.1.1.2 ! misho 271: *data++ = (uint8_t)(0x02 | ASN_LONG_LEN);
! 272: *data++ = (uint8_t)((len >> 8) & 0xFF);
! 273: *data++ = (uint8_t)(len & 0xFF);
1.1 misho 274: }
275: *datalen -= (data - start_data);
276: return (data);
277: }
278:
279:
1.1.1.2 ! misho 280: uint8_t *
! 281: libnet_build_asn1_objid(uint8_t *data, int *datalen, uint8_t type, oid *objid,
1.1 misho 282: int objidlen)
283: {
284: /*
285: * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}*
286: * subidentifier ::= {leadingbyte}* lastbyte
287: * leadingbyte ::= 1 7bitvalue
288: * lastbyte ::= 0 7bitvalue
289: */
290: int asnlen;
291: register oid *op = objid;
1.1.1.2 ! misho 292: uint8_t objid_size[MAX_OID_LEN];
! 293: register uint32_t objid_val;
! 294: uint32_t first_objid_val;
1.1 misho 295: register int i;
296:
297: /* check if there are at least 2 sub-identifiers */
298: if (objidlen < 2)
299: {
300: /* there are not, so make OID have two with value of zero */
301: objid_val = 0;
302: objidlen = 2;
303: }
304: else
305: {
306: /* combine the first two values */
307: objid_val = (op[0] * 40) + op[1];
308: op += 2;
309: }
310: first_objid_val = objid_val;
311:
312: /* calculate the number of bytes needed to store the encoded value */
313: for (i = 1, asnlen = 0;;)
314: {
315: if (objid_val < (unsigned)0x80)
316: {
317: objid_size[i] = 1;
318: asnlen += 1;
319: }
320: else if (objid_val < (unsigned)0x4000)
321: {
322: objid_size[i] = 2;
323: asnlen += 2;
324: }
325: else if (objid_val < (unsigned)0x200000)
326: {
327: objid_size[i] = 3;
328: asnlen += 3;
329: }
330: else if (objid_val < (unsigned)0x10000000)
331: {
332: objid_size[i] = 4;
333: asnlen += 4;
334: }
335: else
336: {
337: objid_size[i] = 5;
338: asnlen += 5;
339: }
340: i++;
341: if (i >= objidlen)
342: {
343: break;
344: }
345: objid_val = *op++;
346: }
347:
348: /* store the ASN.1 tag and length */
349: data = libnet_build_asn1_header(data, datalen, type, asnlen);
350: if (data == NULL || *datalen < asnlen)
351: {
352: return (NULL);
353: }
354:
355: /* store the encoded OID value */
356: for (i = 1, objid_val = first_objid_val, op = objid + 2; i < objidlen; i++)
357: {
358: if (i != 1)
359: {
360: objid_val = *op++;
361: }
362: switch (objid_size[i])
363: {
364: case 1:
1.1.1.2 ! misho 365: *data++ = (uint8_t)objid_val;
1.1 misho 366: break;
367:
368: case 2:
1.1.1.2 ! misho 369: *data++ = (uint8_t)((objid_val >> 7) | 0x80);
! 370: *data++ = (uint8_t)(objid_val & 0x07f);
1.1 misho 371: break;
372: case 3:
1.1.1.2 ! misho 373: *data++ = (uint8_t)((objid_val >> 14) | 0x80);
! 374: *data++ = (uint8_t)((objid_val >> 7 & 0x7f) | 0x80);
! 375: *data++ = (uint8_t)(objid_val & 0x07f);
1.1 misho 376: break;
377:
378: case 4:
1.1.1.2 ! misho 379: *data++ = (uint8_t)((objid_val >> 21) | 0x80);
! 380: *data++ = (uint8_t)((objid_val >> 14 & 0x7f) | 0x80);
! 381: *data++ = (uint8_t)((objid_val >> 7 & 0x7f) | 0x80);
! 382: *data++ = (uint8_t)(objid_val & 0x07f);
1.1 misho 383: break;
384:
385: case 5:
1.1.1.2 ! misho 386: *data++ = (uint8_t)((objid_val >> 28) | 0x80);
! 387: *data++ = (uint8_t)((objid_val >> 21 & 0x7f) | 0x80);
! 388: *data++ = (uint8_t)((objid_val >> 14 & 0x7f) | 0x80);
! 389: *data++ = (uint8_t)((objid_val >> 7 & 0x7f) | 0x80);
! 390: *data++ = (uint8_t)(objid_val & 0x07f);
1.1 misho 391: break;
392: }
393: }
394:
395: /* return the length and data ptagr */
396: *datalen -= asnlen;
397: return (data);
398: }
399:
400:
1.1.1.2 ! misho 401: uint8_t *
! 402: libnet_build_asn1_null(uint8_t *data, int *datalen, uint8_t type)
1.1 misho 403: {
404: /*
405: * ASN.1 null ::= 0x05 0x00
406: */
407: return (libnet_build_asn1_header(data, datalen, type, 0));
408: }
409:
410:
1.1.1.2 ! misho 411: uint8_t *
! 412: libnet_build_asn1_bitstring(uint8_t *data, int *datalen, uint8_t type,
! 413: uint8_t *string, int str_s)
1.1 misho 414: {
415:
416: /*
417: * ASN.1 bit string ::= 0x03 asnlength unused {byte}*
418: */
419: if (str_s < 1 || *string > 7)
420: {
421: return (NULL);
422: }
423: data = libnet_build_asn1_header(data, datalen, type, str_s);
424:
425: if (data == NULL || *datalen < str_s)
426: {
427: return (NULL);
428: }
429:
430: memmove(data, string, str_s);
431: *datalen -= str_s;
432:
433: return (data + str_s);
434: }
435:
436: /* EOF */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>