asn1.c

Go to the documentation of this file.
00001 /*
00002  * Copyright 1998-2007 by egnite Software GmbH
00003  * Copyright 1988, 1989, 1991, 1992 by Carnegie Mellon University
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  * 3. Neither the name of the copyright holders nor the names of
00015  *    contributors may be used to endorse or promote products derived
00016  *    from this software without specific prior written permission.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00019  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00020  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00021  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00022  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00023  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00024  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00025  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00026  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00027  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00028  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00029  * SUCH DAMAGE.
00030  *
00031  * For additional information see http://www.ethernut.de/
00032  */
00033 
00034 #include <sys/types.h>
00035 
00036 #include <stdlib.h>
00037 #include <string.h>
00038 
00039 #include <pro/asn1.h>
00040 
00041 /*
00042  * Abstract Syntax Notation One, ASN.1 as defined in ISO/IS 8824 and 
00043  * ISO/IS 8825. This implements a subset of the above international 
00044  * standards that is sufficient for SNMP.
00045  */
00046 
00057 static CONST uint8_t *AsnLenParse(CONST uint8_t * data, uint32_t * length)
00058 {
00059     uint8_t lengthbyte = *data++;
00060 
00061     if (lengthbyte & ASN_LONG_LEN) {
00062         /* Long length. */
00063         lengthbyte &= ~ASN_LONG_LEN;
00064         if (lengthbyte == 0 || lengthbyte > sizeof(long)) {
00065             return NULL;
00066         }
00067         *length = 0;
00068         while (lengthbyte--) {
00069             *length <<= 8;
00070             *length |= *data++;
00071         }
00072     } else {
00073         /* Short length. */
00074         *length = lengthbyte;
00075     }
00076     return data;
00077 }
00078 
00092 static uint8_t *AsnLenBuild(uint8_t * data, size_t * datalength, size_t length)
00093 {
00094     if (length < 0x80) {
00095         /* Check for buffer overflow. */
00096         if (*datalength < 1) {
00097             return NULL;
00098         }
00099         *datalength -= 1;
00100         *data++ = (uint8_t) length;
00101     } else if (length <= 0xFF) {
00102         /* Check for buffer overflow. */
00103         if (*datalength < 2) {
00104             return NULL;
00105         }
00106         *datalength -= 2;
00107         *data++ = (uint8_t) (0x01 | ASN_LONG_LEN);
00108         *data++ = (uint8_t) length;
00109     } else {
00110         /* Check for buffer overflow. */
00111         if (*datalength < 3) {
00112             return NULL;
00113         }
00114         *datalength -= 3;
00115         *data++ = (uint8_t) (0x02 | ASN_LONG_LEN);
00116         *data++ = (uint8_t) (((unsigned) length >> 8) & 0xFF);
00117         *data++ = (uint8_t) (length & 0xFF);
00118     }
00119     return data;
00120 }
00121 
00135 CONST uint8_t *AsnHeaderParse(CONST uint8_t * data, size_t * datalength, uint8_t * type)
00136 {
00137     size_t header_len;
00138     uint32_t asn_length;
00139     CONST uint8_t *bufp = data;
00140 
00141     if (*datalength <= 0) {
00142         return NULL;
00143     }
00144 
00145     /*
00146      * The first byte of the header is the type. This only
00147      * works on data types < 30, i.e. no extension octets.
00148      */
00149     *type = *bufp;
00150     if ((*type & ASN_EXTENSION_ID) == ASN_EXTENSION_ID) {
00151         return NULL;
00152     }
00153 
00154     /*
00155      * Interpret the length (short or long) of this object.
00156      */
00157     if ((bufp = AsnLenParse(bufp + 1, &asn_length)) == NULL) {
00158         return NULL;
00159     }
00160 
00161     header_len = bufp - data;
00162     /* Data length exceeds packet size. */
00163     if (header_len + asn_length > *datalength) {
00164         return NULL;
00165     }
00166     *datalength = (int) asn_length;
00167 
00168     return bufp;
00169 }
00170 
00188 uint8_t *AsnHeaderBuild(uint8_t * data, size_t * datalength, uint8_t type, size_t length)
00189 {
00190     if (*datalength < 1) {
00191         return NULL;
00192     }
00193     *data++ = type;
00194     (*datalength)--;
00195 
00196     return AsnLenBuild(data, datalength, length);
00197 }
00198 
00214 CONST uint8_t *AsnSequenceParse(CONST uint8_t * data, size_t * datalength, uint8_t type)
00215 {
00216     uint8_t t;
00217 
00218     if ((data = AsnHeaderParse(data, datalength, &t)) != NULL) {
00219         if (t != type) {
00220             data = NULL;
00221         }
00222     }
00223     return data;
00224 }
00225 
00243 uint8_t *AsnSequenceBuild(uint8_t * data, size_t * datalength, uint8_t type, size_t length)
00244 {
00245     if (*datalength < 4) {
00246         /* Not enough space in output packet. */
00247         return NULL;
00248     }
00249 
00250     *datalength -= 4;
00251     *data++ = type;
00252     *data++ = (uint8_t) (0x02 | ASN_LONG_LEN);
00253     *data++ = (uint8_t) (((unsigned) length >> 8) & 0xFF);
00254     *data++ = (uint8_t) length;
00255 
00256     return data;
00257 }
00258 
00276 CONST uint8_t *AsnIntegerParse(CONST uint8_t * data, size_t * datalength, uint8_t * type, long *intp)
00277 {
00278     CONST uint8_t *bufp = data;
00279     uint32_t asn_length;
00280 
00281     /* Get the type. */
00282     *type = *bufp++;
00283     /* Parse the length. */
00284     if ((bufp = AsnLenParse(bufp, &asn_length)) == NULL) {
00285         return NULL;
00286     }
00287     /* Check for overflow. */
00288     if (asn_length > sizeof(long) || asn_length + (bufp - data) > *datalength) {
00289         return NULL;
00290     }
00291     /* Update the number of valid bytes. */
00292     *datalength -= asn_length + (bufp - data);
00293     /* Determine sign. */
00294     if (*bufp & 0x80) {
00295         *intp = -1;
00296     } else {
00297         *intp = 0;
00298     }
00299     /* Retrieve the value. */
00300     while (asn_length--) {
00301         *intp <<= 8;
00302         *intp |= *bufp++;
00303     }
00304     return bufp;
00305 }
00306 
00322 uint8_t *AsnIntegerBuild(uint8_t * data, size_t * datalength, uint8_t type, long *intp)
00323 {
00324     uint32_t mask;
00325     long value = *intp;
00326     size_t size = sizeof(long);
00327 
00328     /*
00329      * Truncate unnecessary bytes off of the most significant end of 
00330      * this 2's complement integer. Skip any leading sequence of 
00331      * 9 consecutive 1's or 0's.
00332      */
00333     mask = 0x1FFUL << ((8 * (sizeof(long) - 1)) - 1);
00334     while (((value & mask) == 0 || (value & mask) == mask) && size > 1) {
00335         size--;
00336         value <<= 8;
00337     }
00338     /* We know the size, so let's build the header. */
00339     if ((data = AsnHeaderBuild(data, datalength, type, size)) == NULL) {
00340         return NULL;
00341     }
00342     /* Check if there's enough space for the value. */
00343     if (*datalength < size) {
00344         return NULL;
00345     }
00346     *datalength -= size;
00347 
00348     /* Store the value, MSB first. */
00349     mask = 0xFFUL << (8 * (sizeof(long) - 1));
00350     while (size--) {
00351         *data++ = (uint8_t) ((value & mask) >> (8 * (sizeof(long) - 1)));
00352         value <<= 8;
00353     }
00354     return data;
00355 }
00356 
00374 CONST uint8_t *AsnUnsignedParse(CONST uint8_t * data, size_t * datalength, uint8_t * type, uint32_t * intp)
00375 {
00376     CONST uint8_t *bufp = data;
00377     uint32_t asn_length;
00378 
00379     /* Get the type. */
00380     *type = *bufp++;
00381     /* Parse the length. */
00382     if ((bufp = AsnLenParse(bufp, &asn_length)) == NULL) {
00383         return NULL;
00384     }
00385     /* Check for length overflow. */
00386     if (asn_length > sizeof(long) + 1 || (asn_length == sizeof(long) + 1 && *bufp != 0x00)) {
00387         return NULL;
00388     }
00389     /* Check for sufficient data. */
00390     if (asn_length + (bufp - data) > *datalength) {
00391         return NULL;
00392     }
00393     /* Update the number of valid bytes. */
00394     *datalength -= (int) asn_length + (bufp - data);
00395     /* Determine sign. */
00396     if (*bufp & 0x80) {
00397         *intp = -1;
00398     } else {
00399         *intp = 0;
00400     }
00401     /* Retrieve the value. */
00402     while (asn_length--) {
00403         *intp <<= 8;
00404         *intp |= *bufp++;
00405     }
00406     return bufp;
00407 }
00408 
00424 uint8_t *AsnUnsignedBuild(uint8_t * data, size_t * datalength, uint8_t type, uint32_t * intp)
00425 {
00426     int msb;
00427     uint32_t mask;
00428     uint32_t value = *intp;
00429     size_t size = sizeof(uint32_t);
00430 
00431     /* Check if MSB is set. */
00432     if (value & (0x80UL << (8 * (sizeof(long) - 1)))) {
00433         msb = 1;
00434         size++;
00435     } else {
00436         msb = 0;
00437         /*
00438          * Truncate unnecessary bytes off of the most significant end.
00439          * Skip any leading sequence of 9 consecutive 1's or 0's.
00440          */
00441         mask = 0x1FFUL << ((8 * (sizeof(long) - 1)) - 1);
00442         while ((((value & mask) == 0) || ((value & mask) == mask)) && size > 1) {
00443             size--;
00444             value <<= 8;
00445         }
00446     }
00447     /* We know the size, so let's build the header. */
00448     if ((data = AsnHeaderBuild(data, datalength, type, size)) == NULL) {
00449         return NULL;
00450     }
00451     /* Check if there's enough space for the value. */
00452     if (*datalength < size) {
00453         return NULL;
00454     }
00455     *datalength -= size;
00456     /* Add leading null byte if MSB set. */
00457     if (msb) {
00458         *data++ = '\0';
00459         size--;
00460     }
00461     /* Store the value, MSB first. */
00462     mask = 0xFFUL << (8 * (sizeof(long) - 1));
00463     while (size--) {
00464         *data++ = (uint8_t) ((value & mask) >> (8 * (sizeof(long) - 1)));
00465         value <<= 8;
00466     }
00467     return data;
00468 }
00469 
00490 CONST uint8_t *AsnOctetStringParse(CONST uint8_t * data, size_t * datalength, uint8_t * type, uint8_t * string, size_t * strlength)
00491 {
00492     CONST uint8_t *bufp = data;
00493     uint32_t asn_length;
00494 
00495     /* Get the type. */
00496     *type = *bufp++;
00497     /* Get the length. */
00498     if ((bufp = AsnLenParse(bufp, &asn_length)) == NULL) {
00499         return NULL;
00500     }
00501     /* Check for overflow. */
00502     if (asn_length > *strlength || asn_length + (bufp - data) > *datalength) {
00503         return NULL;
00504     }
00505     if (asn_length) {
00506         /* Store value and update lengths. */
00507         memcpy(string, bufp, asn_length);
00508         *strlength = (size_t) asn_length;
00509     }
00510     *datalength -= (size_t) (asn_length + (bufp - data));
00511 
00512     return bufp + asn_length;
00513 }
00514 
00532 uint8_t *AsnOctetStringBuild(uint8_t * data, size_t * datalength, uint8_t type, CONST uint8_t * string, size_t strlength)
00533 {
00534     if ((data = AsnHeaderBuild(data, datalength, type, strlength)) == NULL) {
00535         return NULL;
00536     }
00537     if (strlength) {
00538         /* Check for overflow. */
00539         if (*datalength < strlength) {
00540             return NULL;
00541         }
00542         *datalength -= strlength;
00543         if (string) {
00544             memcpy(data, string, strlength);
00545         } else {
00546             memset(data, 0, strlength);
00547         }
00548         data += strlength;
00549     }
00550     return data;
00551 }
00552 
00573 CONST uint8_t *AsnOidParse(CONST uint8_t * data, size_t * datalength, uint8_t * type, OID * objid, size_t * objidlength)
00574 {
00575     CONST uint8_t *bufp = data;
00576     OID *oidp = objid + 1;
00577     uint32_t subidentifier;
00578     long length;
00579     uint32_t asn_length;
00580 
00581     /* Get type and length. */
00582     *type = *bufp++;
00583     if ((bufp = AsnLenParse(bufp, &asn_length)) == NULL) {
00584         return NULL;
00585     }
00586     /* Check for overflow and update number of remaining bytes. */
00587     if (asn_length + (bufp - data) > *datalength) {
00588         /* Message overflow. */
00589         return NULL;
00590     }
00591     *datalength -= (int) asn_length + (bufp - data);
00592 
00593     /* Handle invalid object ID encodings of the form 06 00 robustly. */
00594     if (asn_length == 0) {
00595         objid[0] = objid[1] = 0;
00596     }
00597     length = asn_length;
00598     /* Account for expansion of first byte. */
00599     (*objidlength)--;
00600     while (length > 0 && (*objidlength)-- > 0) {
00601         subidentifier = 0;
00602         /*
00603          * Shift and add in low order 7 bits.
00604          * Last byte has high bit clear.
00605          */
00606         do {
00607             subidentifier = (subidentifier << 7) + (*(uint8_t *) bufp & ~ASN_BIT8);
00608             length--;
00609         } while (*bufp++ & ASN_BIT8);
00610         *oidp++ = (OID) subidentifier;
00611     }
00612 
00613     /*
00614      * The first two subidentifiers are encoded into the first component 
00615      * with the value (X * 40) + Y, where
00616      *
00617      *  X is the value of the first subidentifier.
00618      *  Y is the value of the second subidentifier.
00619      */
00620     subidentifier = objid[1];
00621     if (subidentifier == 0x2B) {
00622         objid[0] = 1;
00623         objid[1] = 3;
00624     } else {
00625         objid[1] = (uint8_t) (subidentifier % 40);
00626         objid[0] = (uint8_t) ((subidentifier - objid[1]) / 40);
00627     }
00628     *objidlength = oidp - objid;
00629 
00630     return bufp;
00631 }
00632 
00649 uint8_t *AsnOidBuild(uint8_t * data, size_t * datalength, uint8_t type, CONST OID * objid, size_t objidlength)
00650 {
00651     uint8_t *buf;
00652     uint32_t objid_val;
00653     uint32_t first_objid_val;
00654     size_t asnlength;
00655     CONST OID *op = objid;
00656     size_t i;
00657 
00658     if (objidlength == 0) {
00659         first_objid_val = 0;
00660         objidlength++;
00661     } else if (objid[0] > 2) {
00662         /* First sub identifier is bad. */
00663         return NULL;
00664     } else if (objidlength == 1) {
00665         first_objid_val = op[0] * 40;
00666     } else if (op[1] > 40 && op[0] < 2) {
00667         /* Second sub identifier is bad. */
00668         return NULL;
00669     } else if (objidlength > MAX_OID_LEN) {
00670         /* Bad object ID length. */
00671         return NULL;
00672     } else {
00673         first_objid_val = op[0] * 40 + op[1];
00674         objidlength--;
00675     }
00676 
00677     /*
00678      * Determine the number of bytes needed to store the encoded value.
00679      */
00680     if ((buf = malloc(MAX_OID_LEN * sizeof(OID))) == NULL) {
00681         return NULL;
00682     }
00683     asnlength = 0;
00684     for (i = 0; i < objidlength; i++) {
00685         if (i) {
00686             objid_val = *op++;
00687         } else {
00688             objid_val = first_objid_val;
00689             op = objid + 2;
00690         }
00691         if (objid_val < 0x80UL) {
00692             buf[i] = 1;
00693             asnlength += 1;
00694         } else if (objid_val < 0x4000UL) {
00695             buf[i] = 2;
00696             asnlength += 2;
00697         } else if (objid_val < 0x200000UL) {
00698             buf[i] = 3;
00699             asnlength += 3;
00700         } else if (objid_val < 0x10000000UL) {
00701             buf[i] = 4;
00702             asnlength += 4;
00703         } else {
00704             buf[i] = 5;
00705             asnlength += 5;
00706         }
00707     }
00708     /* Build the header after knowing the length. */
00709     if ((data = AsnHeaderBuild(data, datalength, type, asnlength)) == NULL || asnlength > *datalength) {
00710         free(buf);
00711         return NULL;
00712     }
00713 
00714     /*
00715      * Store the encoded OID value 
00716      */
00717     for (i = 0; i < objidlength; i++) {
00718         if (i) {
00719             objid_val = *op++;
00720         } else {
00721             objid_val = first_objid_val;
00722             op = objid + 2;
00723         }
00724         switch (buf[i]) {
00725         case 1:
00726             *data++ = (uint8_t) objid_val;
00727             break;
00728         case 2:
00729             *data++ = (uint8_t) ((objid_val >> 7) | 0x80);
00730             *data++ = (uint8_t) (objid_val & 0x07f);
00731             break;
00732         case 3:
00733             *data++ = (uint8_t) ((objid_val >> 14) | 0x80);
00734             *data++ = (uint8_t) ((objid_val >> 7 & 0x7f) | 0x80);
00735             *data++ = (uint8_t) (objid_val & 0x07f);
00736             break;
00737         case 4:
00738             *data++ = (uint8_t) ((objid_val >> 21) | 0x80);
00739             *data++ = (uint8_t) ((objid_val >> 14 & 0x7f) | 0x80);
00740             *data++ = (uint8_t) ((objid_val >> 7 & 0x7f) | 0x80);
00741             *data++ = (uint8_t) (objid_val & 0x07f);
00742             break;
00743         case 5:
00744             *data++ = (uint8_t) ((objid_val >> 28) | 0x80);
00745             *data++ = (uint8_t) ((objid_val >> 21 & 0x7f) | 0x80);
00746             *data++ = (uint8_t) ((objid_val >> 14 & 0x7f) | 0x80);
00747             *data++ = (uint8_t) ((objid_val >> 7 & 0x7f) | 0x80);
00748             *data++ = (uint8_t) (objid_val & 0x07f);
00749             break;
00750         }
00751     }
00752 
00753     *datalength -= asnlength;
00754     free(buf);
00755 
00756     return data;
00757 }
00758 
00774 CONST uint8_t *AsnNullParse(CONST uint8_t * data, size_t * datalength, uint8_t * type)
00775 {
00776     CONST uint8_t *bufp = data;
00777     uint32_t asn_length;
00778 
00779     *type = *bufp++;
00780     if ((bufp = AsnLenParse(bufp, &asn_length)) == NULL) {
00781         return NULL;
00782     }
00783     if (asn_length) {
00784         return NULL;
00785     }
00786     *datalength -= (bufp - data);
00787 
00788     return bufp;
00789 }
00790 
00805 uint8_t *AsnNullBuild(uint8_t * data, size_t * datalength, uint8_t type)
00806 {
00807     return AsnHeaderBuild(data, datalength, type, 0);
00808 }
00809 
00830 CONST uint8_t *AsnBitStringParse(CONST uint8_t * data, size_t * datalength, uint8_t * type, uint8_t * string, size_t * strlength)
00831 {
00832     CONST uint8_t *bufp = data;
00833     uint32_t asn_length;
00834 
00835     *type = *bufp++;
00836     if ((bufp = AsnLenParse(bufp, &asn_length)) == NULL) {
00837         return NULL;
00838     }
00839     if (asn_length + (bufp - data) > *datalength) {
00840         return NULL;
00841     }
00842     if (asn_length < 1 || (size_t) asn_length > *strlength) {
00843         return NULL;
00844     }
00845     if (*bufp > 7) {
00846         return NULL;
00847     }
00848     memcpy(string, bufp, asn_length);
00849     *strlength = (size_t) asn_length;
00850     *datalength -= (size_t) asn_length + (bufp - data);
00851 
00852     return bufp + asn_length;
00853 }
00854 
00872 uint8_t *AsnBitStringBuild(uint8_t * data, size_t * datalength, uint8_t type, CONST uint8_t * string, size_t strlength)
00873 {
00874     if ((data = AsnHeaderBuild(data, datalength, type, strlength)) == NULL) {
00875         return NULL;
00876     }
00877     if (strlength) {
00878         if (strlength > *datalength) {
00879             return NULL;
00880         }
00881         memcpy((char *) data, (char *) string, strlength);
00882         *datalength -= strlength;
00883         data += strlength;
00884     }
00885     return data;
00886 }
00887 
00905 CONST uint8_t *AsnUnsigned64Parse(CONST uint8_t * data, size_t * datalength, uint8_t * type, UNSIGNED64 * cp)
00906 {
00907     CONST uint8_t *bufp = data;
00908     uint32_t asn_length;
00909     uint32_t low = 0;
00910     uint32_t high = 0;
00911     size_t intsize = 4;
00912 
00913     *type = *bufp++;
00914     if ((bufp = AsnLenParse(bufp, &asn_length)) == NULL) {
00915         return NULL;
00916     }
00917     if (asn_length + (bufp - data) > *datalength) {
00918         return NULL;
00919     }
00920     if ((asn_length > (intsize * 2 + 1)) || ((asn_length == (intsize * 2) + 1) && *bufp != 0x00)) {
00921         return NULL;
00922     }
00923     *datalength -= (int) asn_length + (bufp - data);
00924     if (*bufp & 0x80) {
00925         low = (uint32_t) - 1;
00926         high = (uint32_t) - 1;
00927     }
00928     while (asn_length--) {
00929         high = (high << 8) | ((low & 0xFF000000) >> 24);
00930         low = (low << 8) | *bufp++;
00931     }
00932     cp->low = low;
00933     cp->high = high;
00934     return bufp;
00935 }
00936 
00952 uint8_t *AsnUnsigned64Build(uint8_t * data, size_t * datalength, uint8_t type, CONST UNSIGNED64 * cp)
00953 {
00954     uint32_t low;
00955     uint32_t high;
00956     uint32_t mask;
00957     uint32_t mask2;
00958     int add_null_byte = 0;
00959     size_t intsize;
00960 
00961     intsize = 8;
00962     low = cp->low;
00963     high = cp->high;
00964     mask = 0xFFUL << (8 * (sizeof(long) - 1));
00965     /*
00966      * mask is 0xFF000000 on a big-endian machine
00967      */
00968     if ((uint8_t) ((high & mask) >> (8 * (sizeof(long) - 1))) & 0x80) {
00969         /* if MSB is set */
00970         add_null_byte = 1;
00971         intsize++;
00972     }
00973     /*
00974      * Truncate "unnecessary" bytes off of the most significant end of 
00975      * this 2's complement integer.
00976      * There should be no sequence of 9 consecutive 1's or 0's at the most
00977      * significant end of the integer.
00978      */
00979     mask2 = 0x1FFUL << ((8 * (sizeof(long) - 1)) - 1);
00980     /*
00981      * mask2 is 0xFF800000 on a big-endian machine
00982      */
00983     while ((((high & mask2) == 0) || ((high & mask2) == mask2))
00984            && intsize > 1) {
00985         intsize--;
00986         high = (high << 8)
00987             | ((low & mask) >> (8 * (sizeof(long) - 1)));
00988         low <<= 8;
00989     }
00990     data = AsnHeaderBuild(data, datalength, type, intsize);
00991     if (data == NULL || *datalength < intsize) {
00992         return NULL;
00993     }
00994     *datalength -= intsize;
00995     if (add_null_byte == 1) {
00996         *data++ = '\0';
00997         intsize--;
00998     }
00999     while (intsize--) {
01000         *data++ = (uint8_t) ((high & mask) >> (8 * (sizeof(long) - 1)));
01001         high = (high << 8)
01002             | ((low & mask) >> (8 * (sizeof(long) - 1)));
01003         low <<= 8;
01004 
01005     }
01006     return data;
01007 }

© 2000-2007 by egnite Software GmbH - visit http://www.ethernut.de/