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
00039 #include <pro/asn1.h>
00040
00041
00042
00043
00044
00045
00046
00057 static CONST u_char *AsnLenParse(CONST u_char * data, u_long * length)
00058 {
00059 u_char lengthbyte = *data++;
00060
00061 if (lengthbyte & ASN_LONG_LEN) {
00062
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
00074 *length = lengthbyte;
00075 }
00076 return data;
00077 }
00078
00092 static u_char *AsnLenBuild(u_char * data, size_t * datalength, size_t length)
00093 {
00094 if (length < 0x80) {
00095
00096 if (*datalength < 1) {
00097 return NULL;
00098 }
00099 *datalength -= 1;
00100 *data++ = (u_char) length;
00101 } else if (length <= 0xFF) {
00102
00103 if (*datalength < 2) {
00104 return NULL;
00105 }
00106 *datalength -= 2;
00107 *data++ = (u_char) (0x01 | ASN_LONG_LEN);
00108 *data++ = (u_char) length;
00109 } else {
00110
00111 if (*datalength < 3) {
00112 return NULL;
00113 }
00114 *datalength -= 3;
00115 *data++ = (u_char) (0x02 | ASN_LONG_LEN);
00116 *data++ = (u_char) (((unsigned) length >> 8) & 0xFF);
00117 *data++ = (u_char) (length & 0xFF);
00118 }
00119 return data;
00120 }
00121
00135 CONST u_char *AsnHeaderParse(CONST u_char * data, size_t * datalength, u_char * type)
00136 {
00137 size_t header_len;
00138 u_long asn_length;
00139 CONST u_char *bufp = data;
00140
00141 if (*datalength <= 0) {
00142 return NULL;
00143 }
00144
00145
00146
00147
00148
00149 *type = *bufp;
00150 if ((*type & ASN_EXTENSION_ID) == ASN_EXTENSION_ID) {
00151 return NULL;
00152 }
00153
00154
00155
00156
00157 if ((bufp = AsnLenParse(bufp + 1, &asn_length)) == NULL) {
00158 return NULL;
00159 }
00160
00161 header_len = bufp - data;
00162
00163 if (header_len + asn_length > *datalength) {
00164 return NULL;
00165 }
00166 *datalength = (int) asn_length;
00167
00168 return bufp;
00169 }
00170
00188 u_char *AsnHeaderBuild(u_char * data, size_t * datalength, u_char 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 u_char *AsnSequenceParse(CONST u_char * data, size_t * datalength, u_char type)
00215 {
00216 u_char 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 u_char *AsnSequenceBuild(u_char * data, size_t * datalength, u_char type, size_t length)
00244 {
00245 if (*datalength < 4) {
00246
00247 return NULL;
00248 }
00249
00250 *datalength -= 4;
00251 *data++ = type;
00252 *data++ = (u_char) (0x02 | ASN_LONG_LEN);
00253 *data++ = (u_char) (((unsigned) length >> 8) & 0xFF);
00254 *data++ = (u_char) length;
00255
00256 return data;
00257 }
00258
00276 CONST u_char *AsnIntegerParse(CONST u_char * data, size_t * datalength, u_char * type, long *intp)
00277 {
00278 CONST u_char *bufp = data;
00279 u_long asn_length;
00280
00281
00282 *type = *bufp++;
00283
00284 if ((bufp = AsnLenParse(bufp, &asn_length)) == NULL) {
00285 return NULL;
00286 }
00287
00288 if (asn_length > sizeof(long) || asn_length + (bufp - data) > *datalength) {
00289 return NULL;
00290 }
00291
00292 *datalength -= asn_length + (bufp - data);
00293
00294 if (*bufp & 0x80) {
00295 *intp = -1;
00296 } else {
00297 *intp = 0;
00298 }
00299
00300 while (asn_length--) {
00301 *intp <<= 8;
00302 *intp |= *bufp++;
00303 }
00304 return bufp;
00305 }
00306
00322 u_char *AsnIntegerBuild(u_char * data, size_t * datalength, u_char type, long *intp)
00323 {
00324 u_long mask;
00325 long value = *intp;
00326 size_t size = sizeof(long);
00327
00328
00329
00330
00331
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
00339 if ((data = AsnHeaderBuild(data, datalength, type, size)) == NULL) {
00340 return NULL;
00341 }
00342
00343 if (*datalength < size) {
00344 return NULL;
00345 }
00346 *datalength -= size;
00347
00348
00349 mask = 0xFFUL << (8 * (sizeof(long) - 1));
00350 while (size--) {
00351 *data++ = (u_char) ((value & mask) >> (8 * (sizeof(long) - 1)));
00352 value <<= 8;
00353 }
00354 return data;
00355 }
00356
00374 CONST u_char *AsnUnsignedParse(CONST u_char * data, size_t * datalength, u_char * type, u_long * intp)
00375 {
00376 CONST u_char *bufp = data;
00377 u_long asn_length;
00378
00379
00380 *type = *bufp++;
00381
00382 if ((bufp = AsnLenParse(bufp, &asn_length)) == NULL) {
00383 return NULL;
00384 }
00385
00386 if (asn_length > sizeof(long) + 1 || (asn_length == sizeof(long) + 1 && *bufp != 0x00)) {
00387 return NULL;
00388 }
00389
00390 if (asn_length + (bufp - data) > *datalength) {
00391 return NULL;
00392 }
00393
00394 *datalength -= (int) asn_length + (bufp - data);
00395
00396 if (*bufp & 0x80) {
00397 *intp = -1;
00398 } else {
00399 *intp = 0;
00400 }
00401
00402 while (asn_length--) {
00403 *intp <<= 8;
00404 *intp |= *bufp++;
00405 }
00406 return bufp;
00407 }
00408
00424 u_char *AsnUnsignedBuild(u_char * data, size_t * datalength, u_char type, u_long * intp)
00425 {
00426 int msb;
00427 u_long mask;
00428 u_long value = *intp;
00429 size_t size = sizeof(u_long);
00430
00431
00432 if (value & (0x80UL << (8 * (sizeof(long) - 1)))) {
00433 msb = 1;
00434 size++;
00435 } else {
00436 msb = 0;
00437
00438
00439
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
00448 if ((data = AsnHeaderBuild(data, datalength, type, size)) == NULL) {
00449 return NULL;
00450 }
00451
00452 if (*datalength < size) {
00453 return NULL;
00454 }
00455 *datalength -= size;
00456
00457 if (msb) {
00458 *data++ = '\0';
00459 size--;
00460 }
00461
00462 mask = 0xFFUL << (8 * (sizeof(long) - 1));
00463 while (size--) {
00464 *data++ = (u_char) ((value & mask) >> (8 * (sizeof(long) - 1)));
00465 value <<= 8;
00466 }
00467 return data;
00468 }
00469
00490 CONST u_char *AsnOctetStringParse(CONST u_char * data, size_t * datalength, u_char * type, u_char * string, size_t * strlength)
00491 {
00492 CONST u_char *bufp = data;
00493 u_long asn_length;
00494
00495
00496 *type = *bufp++;
00497
00498 if ((bufp = AsnLenParse(bufp, &asn_length)) == NULL) {
00499 return NULL;
00500 }
00501
00502 if (asn_length > *strlength || asn_length + (bufp - data) > *datalength) {
00503 return NULL;
00504 }
00505 if (asn_length) {
00506
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 u_char *AsnOctetStringBuild(u_char * data, size_t * datalength, u_char type, CONST u_char * string, size_t strlength)
00533 {
00534 if ((data = AsnHeaderBuild(data, datalength, type, strlength)) == NULL) {
00535 return NULL;
00536 }
00537 if (strlength) {
00538
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 u_char *AsnOidParse(CONST u_char * data, size_t * datalength, u_char * type, OID * objid, size_t * objidlength)
00574 {
00575 CONST u_char *bufp = data;
00576 OID *oidp = objid + 1;
00577 u_long subidentifier;
00578 long length;
00579 u_long asn_length;
00580
00581
00582 *type = *bufp++;
00583 if ((bufp = AsnLenParse(bufp, &asn_length)) == NULL) {
00584 return NULL;
00585 }
00586
00587 if (asn_length + (bufp - data) > *datalength) {
00588
00589 return NULL;
00590 }
00591 *datalength -= (int) asn_length + (bufp - data);
00592
00593
00594 if (asn_length == 0) {
00595 objid[0] = objid[1] = 0;
00596 }
00597 length = asn_length;
00598
00599 (*objidlength)--;
00600 while (length > 0 && (*objidlength)-- > 0) {
00601 subidentifier = 0;
00602
00603
00604
00605
00606 do {
00607 subidentifier = (subidentifier << 7) + (*(u_char *) bufp & ~ASN_BIT8);
00608 length--;
00609 } while (*bufp++ & ASN_BIT8);
00610 *oidp++ = (OID) subidentifier;
00611 }
00612
00613
00614
00615
00616
00617
00618
00619
00620 subidentifier = objid[1];
00621 if (subidentifier == 0x2B) {
00622 objid[0] = 1;
00623 objid[1] = 3;
00624 } else {
00625 objid[1] = (u_char) (subidentifier % 40);
00626 objid[0] = (u_char) ((subidentifier - objid[1]) / 40);
00627 }
00628 *objidlength = oidp - objid;
00629
00630 return bufp;
00631 }
00632
00649 u_char *AsnOidBuild(u_char * data, size_t * datalength, u_char type, CONST OID * objid, size_t objidlength)
00650 {
00651 u_char *buf;
00652 u_long objid_val;
00653 u_long 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
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
00668 return NULL;
00669 } else if (objidlength > MAX_OID_LEN) {
00670
00671 return NULL;
00672 } else {
00673 first_objid_val = op[0] * 40 + op[1];
00674 objidlength--;
00675 }
00676
00677
00678
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
00709 if ((data = AsnHeaderBuild(data, datalength, type, asnlength)) == NULL || asnlength > *datalength) {
00710 free(buf);
00711 return NULL;
00712 }
00713
00714
00715
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++ = (u_char) objid_val;
00727 break;
00728 case 2:
00729 *data++ = (u_char) ((objid_val >> 7) | 0x80);
00730 *data++ = (u_char) (objid_val & 0x07f);
00731 break;
00732 case 3:
00733 *data++ = (u_char) ((objid_val >> 14) | 0x80);
00734 *data++ = (u_char) ((objid_val >> 7 & 0x7f) | 0x80);
00735 *data++ = (u_char) (objid_val & 0x07f);
00736 break;
00737 case 4:
00738 *data++ = (u_char) ((objid_val >> 21) | 0x80);
00739 *data++ = (u_char) ((objid_val >> 14 & 0x7f) | 0x80);
00740 *data++ = (u_char) ((objid_val >> 7 & 0x7f) | 0x80);
00741 *data++ = (u_char) (objid_val & 0x07f);
00742 break;
00743 case 5:
00744 *data++ = (u_char) ((objid_val >> 28) | 0x80);
00745 *data++ = (u_char) ((objid_val >> 21 & 0x7f) | 0x80);
00746 *data++ = (u_char) ((objid_val >> 14 & 0x7f) | 0x80);
00747 *data++ = (u_char) ((objid_val >> 7 & 0x7f) | 0x80);
00748 *data++ = (u_char) (objid_val & 0x07f);
00749 break;
00750 }
00751 }
00752
00753 *datalength -= asnlength;
00754 free(buf);
00755
00756 return data;
00757 }
00758
00774 CONST u_char *AsnNullParse(CONST u_char * data, size_t * datalength, u_char * type)
00775 {
00776 CONST u_char *bufp = data;
00777 u_long 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 u_char *AsnNullBuild(u_char * data, size_t * datalength, u_char type)
00806 {
00807 return AsnHeaderBuild(data, datalength, type, 0);
00808 }
00809
00830 CONST u_char *AsnBitStringParse(CONST u_char * data, size_t * datalength, u_char * type, u_char * string, size_t * strlength)
00831 {
00832 CONST u_char *bufp = data;
00833 u_long 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 u_char *AsnBitStringBuild(u_char * data, size_t * datalength, u_char type, CONST u_char * 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 u_char *AsnUnsigned64Parse(CONST u_char * data, size_t * datalength, u_char * type, UNSIGNED64 * cp)
00906 {
00907 CONST u_char *bufp = data;
00908 u_long asn_length;
00909 u_long low = 0;
00910 u_long 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 = (u_long) - 1;
00926 high = (u_long) - 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 u_char *AsnUnsigned64Build(u_char * data, size_t * datalength, u_char type, CONST UNSIGNED64 * cp)
00953 {
00954 u_long low;
00955 u_long high;
00956 u_long mask;
00957 u_long 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
00967
00968 if ((u_char) ((high & mask) >> (8 * (sizeof(long) - 1))) & 0x80) {
00969
00970 add_null_byte = 1;
00971 intsize++;
00972 }
00973
00974
00975
00976
00977
00978
00979 mask2 = 0x1FFUL << ((8 * (sizeof(long) - 1)) - 1);
00980
00981
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++ = (u_char) ((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 }