00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include <sys/types.h>
00035
00036 #include <stdlib.h>
00037 #include <string.h>
00038 #include <memdebug.h>
00039
00040 #include <pro/asn1.h>
00041
00042
00043
00044
00045
00046
00047
00058 static CONST uint8_t *AsnLenParse(CONST uint8_t * data, uint32_t * length)
00059 {
00060 uint8_t lengthbyte = *data++;
00061
00062 if (lengthbyte & ASN_LONG_LEN) {
00063
00064 lengthbyte &= ~ASN_LONG_LEN;
00065 if (lengthbyte == 0 || lengthbyte > sizeof(long)) {
00066 return NULL;
00067 }
00068 *length = 0;
00069 while (lengthbyte--) {
00070 *length <<= 8;
00071 *length |= *data++;
00072 }
00073 } else {
00074
00075 *length = lengthbyte;
00076 }
00077 return data;
00078 }
00079
00093 static uint8_t *AsnLenBuild(uint8_t * data, size_t * datalength, size_t length)
00094 {
00095 if (length < 0x80) {
00096
00097 if (*datalength < 1) {
00098 return NULL;
00099 }
00100 *datalength -= 1;
00101 *data++ = (uint8_t) length;
00102 } else if (length <= 0xFF) {
00103
00104 if (*datalength < 2) {
00105 return NULL;
00106 }
00107 *datalength -= 2;
00108 *data++ = (uint8_t) (0x01 | ASN_LONG_LEN);
00109 *data++ = (uint8_t) length;
00110 } else {
00111
00112 if (*datalength < 3) {
00113 return NULL;
00114 }
00115 *datalength -= 3;
00116 *data++ = (uint8_t) (0x02 | ASN_LONG_LEN);
00117 *data++ = (uint8_t) (((unsigned) length >> 8) & 0xFF);
00118 *data++ = (uint8_t) (length & 0xFF);
00119 }
00120 return data;
00121 }
00122
00136 CONST uint8_t *AsnHeaderParse(CONST uint8_t * data, size_t * datalength, uint8_t * type)
00137 {
00138 size_t header_len;
00139 uint32_t asn_length;
00140 CONST uint8_t *bufp = data;
00141
00142 if (*datalength <= 0) {
00143 return NULL;
00144 }
00145
00146
00147
00148
00149
00150 *type = *bufp;
00151 if ((*type & ASN_EXTENSION_ID) == ASN_EXTENSION_ID) {
00152 return NULL;
00153 }
00154
00155
00156
00157
00158 if ((bufp = AsnLenParse(bufp + 1, &asn_length)) == NULL) {
00159 return NULL;
00160 }
00161
00162 header_len = bufp - data;
00163
00164 if (header_len + asn_length > *datalength) {
00165 return NULL;
00166 }
00167 *datalength = (int) asn_length;
00168
00169 return bufp;
00170 }
00171
00189 uint8_t *AsnHeaderBuild(uint8_t * data, size_t * datalength, uint8_t type, size_t length)
00190 {
00191 if (*datalength < 1) {
00192 return NULL;
00193 }
00194 *data++ = type;
00195 (*datalength)--;
00196
00197 return AsnLenBuild(data, datalength, length);
00198 }
00199
00215 CONST uint8_t *AsnSequenceParse(CONST uint8_t * data, size_t * datalength, uint8_t type)
00216 {
00217 uint8_t t;
00218
00219 if ((data = AsnHeaderParse(data, datalength, &t)) != NULL) {
00220 if (t != type) {
00221 data = NULL;
00222 }
00223 }
00224 return data;
00225 }
00226
00244 uint8_t *AsnSequenceBuild(uint8_t * data, size_t * datalength, uint8_t type, size_t length)
00245 {
00246 if (*datalength < 4) {
00247
00248 return NULL;
00249 }
00250
00251 *datalength -= 4;
00252 *data++ = type;
00253 *data++ = (uint8_t) (0x02 | ASN_LONG_LEN);
00254 *data++ = (uint8_t) (((unsigned) length >> 8) & 0xFF);
00255 *data++ = (uint8_t) length;
00256
00257 return data;
00258 }
00259
00277 CONST uint8_t *AsnIntegerParse(CONST uint8_t * data, size_t * datalength, uint8_t * type, long *intp)
00278 {
00279 CONST uint8_t *bufp = data;
00280 uint32_t asn_length;
00281
00282
00283 *type = *bufp++;
00284
00285 if ((bufp = AsnLenParse(bufp, &asn_length)) == NULL) {
00286 return NULL;
00287 }
00288
00289 if (asn_length > sizeof(long) || asn_length + (bufp - data) > *datalength) {
00290 return NULL;
00291 }
00292
00293 *datalength -= asn_length + (bufp - data);
00294
00295 if (*bufp & 0x80) {
00296 *intp = -1;
00297 } else {
00298 *intp = 0;
00299 }
00300
00301 while (asn_length--) {
00302 *intp <<= 8;
00303 *intp |= *bufp++;
00304 }
00305 return bufp;
00306 }
00307
00323 uint8_t *AsnIntegerBuild(uint8_t * data, size_t * datalength, uint8_t type, long *intp)
00324 {
00325 uint32_t mask;
00326 long value = *intp;
00327 size_t size = sizeof(long);
00328
00329
00330
00331
00332
00333
00334 mask = 0x1FFUL << ((8 * (sizeof(long) - 1)) - 1);
00335 while (((value & mask) == 0 || (value & mask) == mask) && size > 1) {
00336 size--;
00337 value <<= 8;
00338 }
00339
00340 if ((data = AsnHeaderBuild(data, datalength, type, size)) == NULL) {
00341 return NULL;
00342 }
00343
00344 if (*datalength < size) {
00345 return NULL;
00346 }
00347 *datalength -= size;
00348
00349
00350 mask = 0xFFUL << (8 * (sizeof(long) - 1));
00351 while (size--) {
00352 *data++ = (uint8_t) ((value & mask) >> (8 * (sizeof(long) - 1)));
00353 value <<= 8;
00354 }
00355 return data;
00356 }
00357
00375 CONST uint8_t *AsnUnsignedParse(CONST uint8_t * data, size_t * datalength, uint8_t * type, uint32_t * intp)
00376 {
00377 CONST uint8_t *bufp = data;
00378 uint32_t asn_length;
00379
00380
00381 *type = *bufp++;
00382
00383 if ((bufp = AsnLenParse(bufp, &asn_length)) == NULL) {
00384 return NULL;
00385 }
00386
00387 if (asn_length > sizeof(long) + 1 || (asn_length == sizeof(long) + 1 && *bufp != 0x00)) {
00388 return NULL;
00389 }
00390
00391 if (asn_length + (bufp - data) > *datalength) {
00392 return NULL;
00393 }
00394
00395 *datalength -= (int) asn_length + (bufp - data);
00396
00397 if (*bufp & 0x80) {
00398 *intp = -1;
00399 } else {
00400 *intp = 0;
00401 }
00402
00403 while (asn_length--) {
00404 *intp <<= 8;
00405 *intp |= *bufp++;
00406 }
00407 return bufp;
00408 }
00409
00425 uint8_t *AsnUnsignedBuild(uint8_t * data, size_t * datalength, uint8_t type, uint32_t * intp)
00426 {
00427 int msb;
00428 uint32_t mask;
00429 uint32_t value = *intp;
00430 size_t size = sizeof(uint32_t);
00431
00432
00433 if (value & (0x80UL << (8 * (sizeof(long) - 1)))) {
00434 msb = 1;
00435 size++;
00436 } else {
00437 msb = 0;
00438
00439
00440
00441
00442 mask = 0x1FFUL << ((8 * (sizeof(long) - 1)) - 1);
00443 while ((((value & mask) == 0) || ((value & mask) == mask)) && size > 1) {
00444 size--;
00445 value <<= 8;
00446 }
00447 }
00448
00449 if ((data = AsnHeaderBuild(data, datalength, type, size)) == NULL) {
00450 return NULL;
00451 }
00452
00453 if (*datalength < size) {
00454 return NULL;
00455 }
00456 *datalength -= size;
00457
00458 if (msb) {
00459 *data++ = '\0';
00460 size--;
00461 }
00462
00463 mask = 0xFFUL << (8 * (sizeof(long) - 1));
00464 while (size--) {
00465 *data++ = (uint8_t) ((value & mask) >> (8 * (sizeof(long) - 1)));
00466 value <<= 8;
00467 }
00468 return data;
00469 }
00470
00491 CONST uint8_t *AsnOctetStringParse(CONST uint8_t * data, size_t * datalength, uint8_t * type, uint8_t * string, size_t * strlength)
00492 {
00493 CONST uint8_t *bufp = data;
00494 uint32_t asn_length;
00495
00496
00497 *type = *bufp++;
00498
00499 if ((bufp = AsnLenParse(bufp, &asn_length)) == NULL) {
00500 return NULL;
00501 }
00502
00503 if (asn_length > *strlength || asn_length + (bufp - data) > *datalength) {
00504 return NULL;
00505 }
00506 if (asn_length) {
00507
00508 memcpy(string, bufp, asn_length);
00509 *strlength = (size_t) asn_length;
00510 }
00511 *datalength -= (size_t) (asn_length + (bufp - data));
00512
00513 return bufp + asn_length;
00514 }
00515
00533 uint8_t *AsnOctetStringBuild(uint8_t * data, size_t * datalength, uint8_t type, CONST uint8_t * string, size_t strlength)
00534 {
00535 if ((data = AsnHeaderBuild(data, datalength, type, strlength)) == NULL) {
00536 return NULL;
00537 }
00538 if (strlength) {
00539
00540 if (*datalength < strlength) {
00541 return NULL;
00542 }
00543 *datalength -= strlength;
00544 if (string) {
00545 memcpy(data, string, strlength);
00546 } else {
00547 memset(data, 0, strlength);
00548 }
00549 data += strlength;
00550 }
00551 return data;
00552 }
00553
00574 CONST uint8_t *AsnOidParse(CONST uint8_t * data, size_t * datalength, uint8_t * type, OID * objid, size_t * objidlength)
00575 {
00576 CONST uint8_t *bufp = data;
00577 OID *oidp = objid + 1;
00578 uint32_t subidentifier;
00579 long length;
00580 uint32_t asn_length;
00581
00582
00583 *type = *bufp++;
00584 if ((bufp = AsnLenParse(bufp, &asn_length)) == NULL) {
00585 return NULL;
00586 }
00587
00588 if (asn_length + (bufp - data) > *datalength) {
00589
00590 return NULL;
00591 }
00592 *datalength -= (int) asn_length + (bufp - data);
00593
00594
00595 if (asn_length == 0) {
00596 objid[0] = objid[1] = 0;
00597 }
00598 length = asn_length;
00599
00600 (*objidlength)--;
00601 while (length > 0 && (*objidlength)-- > 0) {
00602 subidentifier = 0;
00603
00604
00605
00606
00607 do {
00608 subidentifier = (subidentifier << 7) + (*(uint8_t *) bufp & ~ASN_BIT8);
00609 length--;
00610 } while (*bufp++ & ASN_BIT8);
00611 *oidp++ = (OID) subidentifier;
00612 }
00613
00614
00615
00616
00617
00618
00619
00620
00621 subidentifier = objid[1];
00622 if (subidentifier == 0x2B) {
00623 objid[0] = 1;
00624 objid[1] = 3;
00625 } else {
00626 objid[1] = (uint8_t) (subidentifier % 40);
00627 objid[0] = (uint8_t) ((subidentifier - objid[1]) / 40);
00628 }
00629 *objidlength = oidp - objid;
00630
00631 return bufp;
00632 }
00633
00650 uint8_t *AsnOidBuild(uint8_t * data, size_t * datalength, uint8_t type, CONST OID * objid, size_t objidlength)
00651 {
00652 uint8_t *buf;
00653 uint32_t objid_val;
00654 uint32_t first_objid_val;
00655 size_t asnlength;
00656 CONST OID *op = objid;
00657 size_t i;
00658
00659 if (objidlength == 0) {
00660 first_objid_val = 0;
00661 objidlength++;
00662 } else if (objid[0] > 2) {
00663
00664 return NULL;
00665 } else if (objidlength == 1) {
00666 first_objid_val = op[0] * 40;
00667 } else if (op[1] > 40 && op[0] < 2) {
00668
00669 return NULL;
00670 } else if (objidlength > MAX_OID_LEN) {
00671
00672 return NULL;
00673 } else {
00674 first_objid_val = op[0] * 40 + op[1];
00675 objidlength--;
00676 }
00677
00678
00679
00680
00681 if ((buf = malloc(MAX_OID_LEN * sizeof(OID))) == NULL) {
00682 return NULL;
00683 }
00684 asnlength = 0;
00685 for (i = 0; i < objidlength; i++) {
00686 if (i) {
00687 objid_val = *op++;
00688 } else {
00689 objid_val = first_objid_val;
00690 op = objid + 2;
00691 }
00692 if (objid_val < 0x80UL) {
00693 buf[i] = 1;
00694 asnlength += 1;
00695 } else if (objid_val < 0x4000UL) {
00696 buf[i] = 2;
00697 asnlength += 2;
00698 } else if (objid_val < 0x200000UL) {
00699 buf[i] = 3;
00700 asnlength += 3;
00701 } else if (objid_val < 0x10000000UL) {
00702 buf[i] = 4;
00703 asnlength += 4;
00704 } else {
00705 buf[i] = 5;
00706 asnlength += 5;
00707 }
00708 }
00709
00710 if ((data = AsnHeaderBuild(data, datalength, type, asnlength)) == NULL || asnlength > *datalength) {
00711 free(buf);
00712 return NULL;
00713 }
00714
00715
00716
00717
00718 for (i = 0; i < objidlength; i++) {
00719 if (i) {
00720 objid_val = *op++;
00721 } else {
00722 objid_val = first_objid_val;
00723 op = objid + 2;
00724 }
00725 switch (buf[i]) {
00726 case 1:
00727 *data++ = (uint8_t) objid_val;
00728 break;
00729 case 2:
00730 *data++ = (uint8_t) ((objid_val >> 7) | 0x80);
00731 *data++ = (uint8_t) (objid_val & 0x07f);
00732 break;
00733 case 3:
00734 *data++ = (uint8_t) ((objid_val >> 14) | 0x80);
00735 *data++ = (uint8_t) ((objid_val >> 7 & 0x7f) | 0x80);
00736 *data++ = (uint8_t) (objid_val & 0x07f);
00737 break;
00738 case 4:
00739 *data++ = (uint8_t) ((objid_val >> 21) | 0x80);
00740 *data++ = (uint8_t) ((objid_val >> 14 & 0x7f) | 0x80);
00741 *data++ = (uint8_t) ((objid_val >> 7 & 0x7f) | 0x80);
00742 *data++ = (uint8_t) (objid_val & 0x07f);
00743 break;
00744 case 5:
00745 *data++ = (uint8_t) ((objid_val >> 28) | 0x80);
00746 *data++ = (uint8_t) ((objid_val >> 21 & 0x7f) | 0x80);
00747 *data++ = (uint8_t) ((objid_val >> 14 & 0x7f) | 0x80);
00748 *data++ = (uint8_t) ((objid_val >> 7 & 0x7f) | 0x80);
00749 *data++ = (uint8_t) (objid_val & 0x07f);
00750 break;
00751 }
00752 }
00753
00754 *datalength -= asnlength;
00755 free(buf);
00756
00757 return data;
00758 }
00759
00775 CONST uint8_t *AsnNullParse(CONST uint8_t * data, size_t * datalength, uint8_t * type)
00776 {
00777 CONST uint8_t *bufp = data;
00778 uint32_t asn_length;
00779
00780 *type = *bufp++;
00781 if ((bufp = AsnLenParse(bufp, &asn_length)) == NULL) {
00782 return NULL;
00783 }
00784 if (asn_length) {
00785 return NULL;
00786 }
00787 *datalength -= (bufp - data);
00788
00789 return bufp;
00790 }
00791
00806 uint8_t *AsnNullBuild(uint8_t * data, size_t * datalength, uint8_t type)
00807 {
00808 return AsnHeaderBuild(data, datalength, type, 0);
00809 }
00810
00831 CONST uint8_t *AsnBitStringParse(CONST uint8_t * data, size_t * datalength, uint8_t * type, uint8_t * string, size_t * strlength)
00832 {
00833 CONST uint8_t *bufp = data;
00834 uint32_t asn_length;
00835
00836 *type = *bufp++;
00837 if ((bufp = AsnLenParse(bufp, &asn_length)) == NULL) {
00838 return NULL;
00839 }
00840 if (asn_length + (bufp - data) > *datalength) {
00841 return NULL;
00842 }
00843 if (asn_length < 1 || (size_t) asn_length > *strlength) {
00844 return NULL;
00845 }
00846 if (*bufp > 7) {
00847 return NULL;
00848 }
00849 memcpy(string, bufp, asn_length);
00850 *strlength = (size_t) asn_length;
00851 *datalength -= (size_t) asn_length + (bufp - data);
00852
00853 return bufp + asn_length;
00854 }
00855
00873 uint8_t *AsnBitStringBuild(uint8_t * data, size_t * datalength, uint8_t type, CONST uint8_t * string, size_t strlength)
00874 {
00875 if ((data = AsnHeaderBuild(data, datalength, type, strlength)) == NULL) {
00876 return NULL;
00877 }
00878 if (strlength) {
00879 if (strlength > *datalength) {
00880 return NULL;
00881 }
00882 memcpy((char *) data, (char *) string, strlength);
00883 *datalength -= strlength;
00884 data += strlength;
00885 }
00886 return data;
00887 }
00888
00906 CONST uint8_t *AsnUnsigned64Parse(CONST uint8_t * data, size_t * datalength, uint8_t * type, UNSIGNED64 * cp)
00907 {
00908 CONST uint8_t *bufp = data;
00909 uint32_t asn_length;
00910 uint32_t low = 0;
00911 uint32_t high = 0;
00912 size_t intsize = 4;
00913
00914 *type = *bufp++;
00915 if ((bufp = AsnLenParse(bufp, &asn_length)) == NULL) {
00916 return NULL;
00917 }
00918 if (asn_length + (bufp - data) > *datalength) {
00919 return NULL;
00920 }
00921 if ((asn_length > (intsize * 2 + 1)) || ((asn_length == (intsize * 2) + 1) && *bufp != 0x00)) {
00922 return NULL;
00923 }
00924 *datalength -= (int) asn_length + (bufp - data);
00925 if (*bufp & 0x80) {
00926 low = (uint32_t) - 1;
00927 high = (uint32_t) - 1;
00928 }
00929 while (asn_length--) {
00930 high = (high << 8) | ((low & 0xFF000000) >> 24);
00931 low = (low << 8) | *bufp++;
00932 }
00933 cp->low = low;
00934 cp->high = high;
00935 return bufp;
00936 }
00937
00953 uint8_t *AsnUnsigned64Build(uint8_t * data, size_t * datalength, uint8_t type, CONST UNSIGNED64 * cp)
00954 {
00955 uint32_t low;
00956 uint32_t high;
00957 uint32_t mask;
00958 uint32_t mask2;
00959 int add_null_byte = 0;
00960 size_t intsize;
00961
00962 intsize = 8;
00963 low = cp->low;
00964 high = cp->high;
00965 mask = 0xFFUL << (8 * (sizeof(long) - 1));
00966
00967
00968
00969 if ((uint8_t) ((high & mask) >> (8 * (sizeof(long) - 1))) & 0x80) {
00970
00971 add_null_byte = 1;
00972 intsize++;
00973 }
00974
00975
00976
00977
00978
00979
00980 mask2 = 0x1FFUL << ((8 * (sizeof(long) - 1)) - 1);
00981
00982
00983
00984 while ((((high & mask2) == 0) || ((high & mask2) == mask2))
00985 && intsize > 1) {
00986 intsize--;
00987 high = (high << 8)
00988 | ((low & mask) >> (8 * (sizeof(long) - 1)));
00989 low <<= 8;
00990 }
00991 data = AsnHeaderBuild(data, datalength, type, intsize);
00992 if (data == NULL || *datalength < intsize) {
00993 return NULL;
00994 }
00995 *datalength -= intsize;
00996 if (add_null_byte == 1) {
00997 *data++ = '\0';
00998 intsize--;
00999 }
01000 while (intsize--) {
01001 *data++ = (uint8_t) ((high & mask) >> (8 * (sizeof(long) - 1)));
01002 high = (high << 8)
01003 | ((low & mask) >> (8 * (sizeof(long) - 1)));
01004 low <<= 8;
01005
01006 }
01007 return data;
01008 }