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>