1implement ASN1; 2 3include "sys.m"; 4 sys: Sys; 5 6include "asn1.m"; 7 8# Masks 9TAG_MASK : con 16r1F; 10CONSTR_MASK : con 16r20; 11CLASS_MASK : con 16rC0; 12 13# Decoding errors 14OK, ESHORT, ETOOBIG, EVALLEN, ECONSTR, EPRIM, EINVAL, EUNIMPL: con iota; 15 16debug : con 0; 17 18init() 19{ 20 sys = load Sys Sys->PATH; 21} 22 23# Decode the whole array as a BER encoding of an ASN1 type. 24# If there's an error, the return string will contain the error. 25# Depending on the error, the returned elem may or may not 26# be nil. 27decode(a: array of byte) : (string, ref Elem) 28{ 29 (ecode, i, elem) := ber_decode(a, 0, len a); 30 return (errstr(ecode, i, len a), elem); 31} 32 33# Like decode, but continue decoding after first element 34# of array ends. 35decode_seq(a: array of byte) : (string, list of ref Elem) 36{ 37 (ecode, i, elist) := seq_decode(a, 0, len a, -1, 1); 38 return (errstr(ecode, i, len a), elist); 39} 40 41# Decode the whole array as a BER encoding of an ASN1 value, 42# (i.e., the part after the tag and length). 43# Assume the value is encoded as universal tag "kind". 44# The constr arg is 1 if the value is constructed, 0 if primitive. 45# If there's an error, the return string will contain the error. 46# Depending on the error, the returned value may or may not 47# be nil. 48decode_value(a: array of byte, kind, constr: int) : (string, ref Value) 49{ 50 n := len a; 51 (ecode, i, val) := value_decode(a, 0, n, n, kind, constr); 52 return (errstr(ecode, i, len a), val); 53} 54 55# The rest of the decoding routines take the array (a), the 56# starting position (i), and the ending position +1 (n). 57# They return (err code, new i, [... varies]). 58 59# for debugging 60ber_ind := ""; 61ber_ind_save := ""; 62 63# Decode an ASN1 (tag, length, value). 64ber_decode(a: array of byte, i, n: int) : (int, int, ref Elem) 65{ 66 if(debug) { 67 ber_ind_save = ber_ind; 68 ber_ind = ber_ind + " "; 69 sys->print("%sber_decode, byte %d\n", ber_ind, i); 70 } 71 err, length: int; 72 tag : Tag; 73 val : ref Value; 74 elem : ref Elem = nil; 75 (err, i, tag) = tag_decode(a, i, n); 76 if(err == OK) { 77 (err, i, length) = length_decode(a, i, n); 78 if(err == OK) { 79 if(debug) 80 sys->print("%sgot tag %s, length %d, now at byte %d\n", 81 ber_ind, tag.tostring(), length, i); 82 if(tag.class == Universal) 83 (err, i, val) = value_decode(a, i, n, length, tag.num, tag.constr); 84 else 85 (err, i, val) = value_decode(a, i, n, length, OCTET_STRING, 0); 86 if(val != nil) 87 elem = ref Elem(tag, val); 88 } 89 } 90 if(debug) { 91 sys->print("%send ber_decode, byte %d\n", ber_ind, i); 92 if(val != nil) { 93 sys->print("%sdecode result:\n", ber_ind); 94 print_elem(elem); 95 } 96 if(err != OK) 97 sys->print("%serror: %s\n", ber_ind, errstr(err, i, i)); 98 ber_ind = ber_ind_save; 99 } 100 return (err, i, elem); 101} 102 103# Decode a tag field. As well as Tag, return an int that 104# is 1 if the type is constructed, 0 if not. 105tag_decode(a: array of byte, i, n: int) : (int, int, Tag) 106{ 107 err := OK; 108 class, num, constr: int; 109 if(n-i >= 2) { 110 v := int a[i++]; 111 class = v & CLASS_MASK; 112 if(v & CONSTR_MASK) 113 constr = 1; 114 else 115 constr = 0; 116 num = v & TAG_MASK; 117 if(num == TAG_MASK) 118 # long tag number 119 (err, i, num) = uint7_decode(a, i, n); 120 } 121 else 122 err = ESHORT; 123 return (err, i, Tag(class, num, constr)); 124} 125 126# Decode a length field. Assume it fits in a Limbo int. 127# If "indefinite length", return -1. 128length_decode(a: array of byte, i, n: int) : (int, int, int) 129{ 130 err := OK; 131 num := 0; 132 if(i < n) { 133 v := int a[i++]; 134 if(v & 16r80) 135 return int_decode(a, i, n, v&16r7F, 1); 136 else if(v == 16r80) 137 num = -1; 138 else 139 num = v; 140 } 141 else 142 err = ESHORT; 143 return (err, i, num); 144} 145 146# Decode a value according to the encoding of the Universal 147# type with number "kind" and constructed/primitive according 148# to "constr", with given length (may be -1, for "indefinite"). 149value_decode(a: array of byte, i, n, length, kind, constr: int) : (int, int, ref Value) 150{ 151 err := OK; 152 val : ref Value; 153 va : array of byte; 154 if(length == -1) { 155 if(!constr) 156 err = EINVAL; 157 } 158 else if(i+length > n) 159 err = EVALLEN; 160 if(err != OK) 161 return (err, i, nil); 162 case kind { 163 0 => 164 # marker for end of indefinite constructions 165 if(length == 0) 166 val = ref Value.EOC; 167 else 168 err = EINVAL; 169 BOOLEAN => 170 if(constr) 171 err = ECONSTR; 172 else if(length != 1) 173 err = EVALLEN; 174 else { 175 val = ref Value.Bool(int a[0]); 176 i++; 177 } 178 INTEGER or ENUMERATED => 179 if(constr) 180 err = ECONSTR; 181 else if(length <= 4) { 182 num : int; 183 (err, i, num) = int_decode(a, i, i+length, length, 0); 184 if(err == OK) 185 val = ref Value.Int(num); 186 } 187 else { 188 va = array[length] of byte; 189 va[0:] = a[i:i+length]; 190 val = ref Value.BigInt(va); 191 i += length; 192 } 193 BIT_STRING => 194 if(constr) { 195 if(length == -1 && i+2 <= n && a[i] == byte 0 && a[i+1] == byte 0) { 196 val = ref Value.BitString(0, nil); 197 i += 2; 198 } 199 else 200 # TODO: recurse and concat results 201 err = EUNIMPL; 202 } 203 else { 204 if(length < 2) { 205 if(length == 1 && a[0] == byte 0) { 206 val = ref Value.BitString(0, nil); 207 i ++; 208 } 209 else 210 err = EINVAL; 211 } 212 else { 213 bitsunused := int a[i]; 214 if(bitsunused > 7) 215 err = EINVAL; 216 else if(length > 16r0FFFFFFF) 217 err = ETOOBIG; 218 else { 219 va = array[length-1] of byte; 220 va[0:] = a[i+1:i+length]; 221 val = ref Value.BitString(bitsunused, va); 222 i += length; 223 } 224 } 225 } 226 OCTET_STRING or ObjectDescriptor => 227 (err, i, va) = octet_decode(a, i, n, length, constr); 228 if(err == OK) 229 val = ref Value.Octets(va); 230 NULL => 231 if(constr) 232 err = ECONSTR; 233 else if(length != 0) 234 err = EVALLEN; 235 else 236 val = ref Value.Null; 237 OBJECT_ID => 238 if(constr) 239 err = ECONSTR; 240 else if (length == 0) 241 err = EVALLEN; 242 else { 243 subids : list of int = nil; 244 iend := i+length; 245 while(i < iend) { 246 x : int; 247 (err, i, x) = uint7_decode(a, i, n); 248 if(err != OK) 249 break; 250 subids = x :: subids; 251 } 252 if(err == OK) { 253 if(i != iend) 254 err = EVALLEN; 255 else { 256 m := len subids; 257 ia := array[m+1] of int; 258 while(subids != nil) { 259 y := hd subids; 260 subids = tl subids; 261 if(m == 1) { 262 ia[1] = y % 40; 263 ia[0] = y / 40; 264 } 265 else 266 ia[m--] = y; 267 } 268 val = ref Value.ObjId(ref Oid(ia)); 269 } 270 } 271 } 272 EXTERNAL or EMBEDDED_PDV => 273 # TODO: parse this internally 274 va = array[length] of byte; 275 va[0:] = a[i:i+length]; 276 val = ref Value.Other(va); 277 i += length; 278 REAL => 279 # let the appl decode, with math module 280 if(constr) 281 err = ECONSTR; 282 else { 283 va = array[length] of byte; 284 va[0:] = a[i:i+length]; 285 val = ref Value.Real(va); 286 i += length; 287 } 288 SEQUENCE or SET=> 289 vl : list of ref Elem; 290 (err, i, vl) = seq_decode(a, i, n, length, constr); 291 if(err == OK) { 292 if(kind == SEQUENCE) 293 val = ref Value.Seq(vl); 294 else 295 val = ref Value.Set(vl); 296 } 297 NumericString or PrintableString or TeletexString 298 or VideotexString or IA5String or UTCTime 299 or GeneralizedTime or GraphicString or VisibleString 300 or GeneralString or UniversalString or BMPString => 301 (err, i, va) = octet_decode(a, i, n, length, constr); 302 if(err == OK) 303 # sometimes wrong: need to do char set conversion 304 val = ref Value.String(string va); 305 306 * => 307 va = array[length] of byte; 308 va[0:] = a[i:i+length]; 309 val = ref Value.Other(va); 310 i += length; 311 } 312 return (err, i, val); 313} 314 315# Decode an int in format where count bytes are 316# concatenated to form value. 317# Although ASN1 allows any size integer, we return 318# an error if the result doesn't fit in a Limbo int. 319# If unsigned is not set, make sure to propagate sign bit. 320int_decode(a: array of byte, i, n, count, unsigned: int) : (int, int, int) 321{ 322 err := OK; 323 num := 0; 324 if(n-i >= count) { 325 if((count > 4) || (unsigned && count == 4 && (int a[i] & 16r80))) 326 err = ETOOBIG; 327 else { 328 if(!unsigned && count > 0 && count < 4 && (int a[i] & 16r80)) 329 num = -1; # all bits set 330 for(j := 0; j < count; j++) { 331 v := int a[i++]; 332 num = (num << 8) | v; 333 } 334 } 335 } 336 else 337 err = ESHORT; 338 return (err, i, num); 339} 340 341# Decode an unsigned int in format where each 342# byte except last has high bit set, and remaining 343# seven bits of each byte are concatenated to form value. 344# Although ASN1 allows any size integer, we return 345# an error if the result doesn't fit in a Limbo int. 346uint7_decode(a: array of byte, i, n: int) : (int, int, int) 347{ 348 err := OK; 349 num := 0; 350 more := 1; 351 while(more && i < n) { 352 v := int a[i++]; 353 if(num & 16r7F000000) { 354 err = ETOOBIG; 355 break; 356 } 357 num <<= 7; 358 more = v & 16r80; 359 num |= (v & 16r7F); 360 } 361 if(n == i) 362 err = ESHORT; 363 return (err, i, num); 364} 365 366# Decode an octet string, recursively if constr. 367# We've already checked that length==-1 implies constr==1, 368# and otherwise that specified length fits within a[i..n]. 369octet_decode(a: array of byte, i, n, length, constr: int) : (int, int, array of byte) 370{ 371 err := OK; 372 va : array of byte; 373 if(length >= 0 && !constr) { 374 va = array[length] of byte; 375 va[0:] = a[i:i+length]; 376 i += length; 377 } 378 else { 379 # constructed, either definite or indefinite length 380 lva : list of array of byte = nil; 381 elem : ref Elem; 382 istart := i; 383 totbytes := 0; 384 cloop: 385 for(;;) { 386 if(length >= 0 && i >= istart+length) { 387 if(i != istart+length) 388 err = EVALLEN; 389 break cloop; 390 } 391 oldi := i; 392 (err, i, elem) = ber_decode(a, i, n); 393 if(err != OK) 394 break; 395 pick v := elem.val { 396 Octets => 397 lva = v.bytes :: lva; 398 totbytes += len v.bytes; 399 EOC => 400 if(length != -1) { 401 i = oldi; 402 err = EINVAL; 403 } 404 break cloop; 405 * => 406 i = oldi; 407 err = EINVAL; 408 break cloop; 409 } 410 } 411 if(err == OK) { 412 va = array[totbytes] of byte; 413 j := totbytes; 414 while(lva != nil) { 415 x := hd lva; 416 lva = tl lva; 417 m := len x; 418 va[j-m:] = x[0:]; 419 j -= m; 420 } 421 } 422 } 423 return (err, i, va); 424} 425 426# Decode a sequence or set. 427# We've already checked that length==-1 implies constr==1, 428# and otherwise that specified length fits within a[i..n]. 429seq_decode(a : array of byte, i, n, length, constr: int) : (int, int, list of ref Elem) 430{ 431 err := OK; 432 ans : list of ref Elem = nil; 433 if(!constr) 434 err = EPRIM; 435 else { 436 # constructed, either definite or indefinite length 437 lve : list of ref Elem = nil; 438 elem : ref Elem; 439 istart := i; 440 cloop: 441 for(;;) { 442 if(length >= 0 && i >= istart+length) { 443 if(i != istart+length) 444 err = EVALLEN; 445 break cloop; 446 } 447 oldi := i; 448 (err, i, elem) = ber_decode(a, i, n); 449 if(err != OK) 450 break; 451 pick v := elem.val { 452 EOC => 453 if(length != -1) { 454 i = oldi; 455 err = EINVAL; 456 } 457 break cloop; 458 * => 459 lve = elem :: lve; 460 } 461 } 462 if(err == OK) { 463 # reverse back to original order 464 while(lve != nil) { 465 e := hd lve; 466 lve = tl lve; 467 ans = e :: ans; 468 } 469 } 470 } 471 return (err, i, ans); 472} 473 474# Encode e by BER rules 475encode(e: ref Elem) : (string, array of byte) 476{ 477 (err, n) := enc(nil, e, 0, 1); 478 if(err != "") 479 return (err, nil); 480 b := array[n] of byte; 481 enc(b, e, 0, 0); 482 return ("", b); 483} 484 485# Encode e into array b, only putting in bytes if !lenonly. 486# Start at loc i, return index after. 487enc(b: array of byte, e: ref Elem, i, lenonly: int) : (string, int) 488{ 489 (err, vlen, constr) := val_enc(b, e, 0, 1); 490 if(err != "") 491 return (err, i); 492 tag := e.tag; 493 v := tag.class | constr; 494 if(tag.num < 31) { 495 if(!lenonly) 496 b[i] = byte (v | tag.num); 497 i++; 498 } 499 else { 500 if(!lenonly) 501 b[i] = byte (v | 31); 502 if(tag.num < 0) 503 return ("negative tag number", i); 504 i = uint7_enc(b, tag.num, i+1, lenonly); 505 } 506 if(vlen < 16r80) { 507 if(!lenonly) 508 b[i] = byte vlen; 509 i++; 510 } 511 else { 512 ilen := int_enc(b, vlen, 1, 0, 1); 513 if(!lenonly) { 514 b[i] = byte (16r80 | ilen); 515 i = int_enc(b, vlen, 1, i+1, 0); 516 } 517 else 518 i += 1+ilen; 519 } 520 if(!lenonly) 521 val_enc(b, e, i, 0); 522 i += vlen; 523 return ("", i); 524} 525 526# Encode e.val into array b, only putting in bytes if !lenonly. 527# Start at loc i, return (err, index after, constructed or primitive) 528val_enc(b: array of byte, e: ref Elem, i, lenonly: int) : (string, int, int) 529{ 530 kind := e.tag.num; 531 cl := e.tag.class; 532 ok := 1; 533 v : int; 534 bb : array of byte; 535 constr := 0; 536 if(cl != Universal) { 537 pick vv := e.val { 538 Bool => 539 kind = BOOLEAN; 540 Int => 541 kind = INTEGER; 542 BigInt => 543 kind = INTEGER; 544 Octets => 545 kind = OCTET_STRING; 546 Real => 547 kind = REAL; 548 Other => 549 kind = OCTET_STRING; 550 BitString => 551 kind = BIT_STRING; 552 Null => 553 kind = NULL; 554 ObjId => 555 kind = OBJECT_ID; 556 String => 557 kind = UniversalString; 558 Seq => 559 kind = SEQUENCE; 560 Set => 561 kind = SET; 562 } 563 } 564 case kind { 565 BOOLEAN => 566 (ok, v) = e.is_int(); 567 if(ok) { 568 if(v != 0) 569 v = 255; 570 i = int_enc(b, v, 1, i, lenonly); 571 } 572 INTEGER or ENUMERATED => 573 (ok, v) = e.is_int(); 574 if(ok) 575 i = int_enc(b, v, 0, i, lenonly); 576 else { 577 (ok, bb) = e.is_bigint(); 578 if(ok) { 579 if(!lenonly) 580 b[i:] = bb; 581 i += len bb; 582 } 583 } 584 BIT_STRING => 585 (ok, v, bb) = e.is_bitstring(); 586 if(ok) { 587 if(bb == nil) { 588 if(!lenonly) 589 b[i] = byte 0; 590 i++; 591 } 592 else { 593 if(v < 0 || v > 7) 594 ok = 0; 595 else { 596 if(!lenonly) { 597 b[i] = byte v; 598 b[i+1:] = bb; 599 } 600 i += 1 + len bb; 601 } 602 } 603 } 604 OCTET_STRING or ObjectDescriptor or EXTERNAL or REAL 605 or EMBEDDED_PDV => 606 pick vv := e.val { 607 Octets or Real or Other => 608 if(!lenonly && vv.bytes != nil) 609 b[i:] = vv.bytes; 610 i += len vv.bytes; 611 * => 612 ok = 0; 613 } 614 NULL => 615 ; 616 OBJECT_ID => 617 oid : ref Oid; 618 (ok, oid) = e.is_oid(); 619 if(ok) { 620 n := len oid.nums; 621 for(k := 0; k < n; k++) { 622 v = oid.nums[k]; 623 if(k == 0) { 624 v *= 40; 625 if(n > 1) 626 v += oid.nums[++k]; 627 } 628 i = uint7_enc(b, v, i, lenonly); 629 } 630 } 631 SEQUENCE or SET => 632 pick vv := e.val { 633 Seq or Set => 634 constr = CONSTR_MASK; 635 for(l := vv.l; l != nil; l = tl l) { 636 err : string; 637 (err, i) = enc(b, hd l, i, lenonly); 638 if(err != "") 639 return (err, i, 0); 640 } 641 } 642 NumericString or PrintableString or TeletexString 643 or VideotexString or IA5String or UTCTime 644 or GeneralizedTime or GraphicString or VisibleString 645 or GeneralString or UniversalString or BMPString => 646 pick vv := e.val { 647 String => 648 bb = array of byte vv.s; 649 if(!lenonly && bb != nil) 650 b[i:] = bb; 651 i += len bb; 652 * => 653 ok = 0; 654 } 655 * => 656 ok = 0; 657 } 658 if(!ok) 659 return ("bad value for encoding kind", i, constr); 660 return ("", i, constr); 661} 662 663# Encode num as unsigned 7 bit values with top bit 1 on all bytes 664# except last, into array b, only putting in bytes if !lenonly. 665# Start at loc i, return index after. 666uint7_enc(b: array of byte, num, i, lenonly: int) : int 667{ 668 n := 1; 669 v := num>>7; 670 while(v > 0) { 671 v >>= 7; 672 n++; 673 } 674 if(lenonly) 675 i += n; 676 else { 677 for(k := (n-1)*7; k > 0; k -= 7) 678 b[i++] = byte ((num>>k) | 16r80); 679 b[i++] = byte (num & 16r7F); 680 } 681 return i; 682} 683 684# Encode num as unsigned or signed integer into array b, 685# only putting in bytes if !lenonly. 686# Encoding is length followed by bytes to concatenate. 687# Start at loc i, return index after. 688int_enc(b: array of byte, num, unsigned, i, lenonly: int) : int 689{ 690 v := num; 691 if(v < 0) 692 v = -(v+1); 693 n := 1; 694 prevv := v; 695 v >>= 8; 696 while(v > 0) { 697 prevv = v; 698 v >>= 8; 699 n++; 700 } 701 if(!unsigned && (prevv & 16r80)) 702 n++; 703 if(lenonly) 704 i += n; 705 else { 706 for(k := (n-1)*8; k >= 0; k -= 8) 707 b[i++] = byte (num>>k); 708 } 709 return i; 710} 711 712# Compare two arrays of integers; return true if they match 713intarr_eq(a: array of int, b: array of int) : int 714{ 715 alen := len a; 716 if(alen != len b) 717 return 0; 718 for(i := 0; i < alen; i++) 719 if(a[i] != b[i]) 720 return 0; 721 return 1; 722} 723 724# Look for o in tab; if found, return index, else return -1. 725oid_lookup(o: ref Oid, tab: array of Oid) : int 726{ 727 for(i := 0; i < len tab; i++) 728 if(intarr_eq(o.nums, tab[i].nums)) 729 return i; 730 return -1; 731} 732 733# If e is a SEQUENCE, return (1, e's element list) 734# else return (error, nil). 735Elem.is_seq(e: self ref Elem) : (int, list of ref Elem) 736{ 737 if(e.tag.class == Universal && e.tag.num == SEQUENCE) { 738 pick v := e.val { 739 Seq => 740 return (1, v.l); 741 } 742 } 743 return (0, nil); 744} 745 746# If e is a SET, return (1, e's element list) 747# else return (error, nil). 748Elem.is_set(e: self ref Elem) : (int, list of ref Elem) 749{ 750 if(e.tag.class == Universal && e.tag.num == SET) { 751 pick v := e.val { 752 Set => 753 return (1, v.l); 754 } 755 } 756 return (0, nil); 757} 758 759# If e is an INTEGER that fits in a limbo int, return (1, val) 760# else return (0, 0l). 761Elem.is_int(e: self ref Elem) : (int, int) 762{ 763 if(e.tag.class == Universal && (e.tag.num == INTEGER || e.tag.num == BOOLEAN)) { 764 pick v := e.val { 765 Bool or 766 Int => 767 return (1, v.v); 768 } 769 } 770 return (0, 0); 771} 772 773# If e is an INTEGER that doesn't fit in a limbo int, return (1, bytes), 774# or even if it does fit, return it as an array of bytes. 775# else return (0, nil). 776Elem.is_bigint(e: self ref Elem) : (int, array of byte) 777{ 778 if(e.tag.class == Universal && e.tag.num == INTEGER) { 779 pick v := e.val { 780 BigInt => 781 return (1, v.bytes); 782 Int => 783 x := v.v; 784 a := array[4] of byte; 785 for(i := 0; i < 4; i++) 786 a[i] = byte ((x >> (8*(3-i))) & 16rFF); 787 for(j := 0; j < 3; j++) 788 if(a[j] != byte 0) 789 break; 790 return (1, a[j:]); 791 } 792 } 793 return (0, nil); 794} 795 796# If e is a bitstring, return (1, unused bits, bytes containing bit string), 797# else return (0, nil) 798Elem.is_bitstring(e: self ref Elem) : (int, int, array of byte) 799{ 800 if(e.tag.class == Universal && e.tag.num == BIT_STRING) { 801 pick v := e.val { 802 BitString => 803 return (1, v.unusedbits, v.bits); 804 } 805 } 806 return (0, 0, nil); 807} 808 809# If e is an octetstring, return (1, bytes), 810# else return (0, nil) 811Elem.is_octetstring(e: self ref Elem) : (int, array of byte) 812{ 813 if(e.tag.class == Universal && e.tag.num == OCTET_STRING) { 814 pick v := e.val { 815 Octets => 816 return (1, v.bytes); 817 } 818 } 819 return (0, nil); 820} 821 822# If e is an object id, return (1, ref Oid), 823# else return (0, nil) 824Elem.is_oid(e: self ref Elem) : (int, ref Oid) 825{ 826 if(e.tag.class == Universal && e.tag.num == OBJECT_ID) { 827 pick v := e.val { 828 ObjId => 829 return (1, v.id); 830 } 831 } 832 return (0, nil); 833} 834 835# If e is some kind of string (excluding times), return (1, string), 836# else return (0, "") 837Elem.is_string(e: self ref Elem) : (int, string) 838{ 839 if(e.tag.class == Universal) { 840 case e.tag.num { 841 NumericString or PrintableString or TeletexString 842 or VideotexString or IA5String or GraphicString 843 or VisibleString or GeneralString or UniversalString 844 or BMPString => 845 pick v := e.val { 846 String => 847 return (1, v.s); 848 } 849 } 850 } 851 return (0, nil); 852} 853 854# If e is some kind of time, return (1, string), 855# else return (0, "") 856Elem.is_time(e: self ref Elem) : (int, string) 857{ 858 if(e.tag.class == Universal 859 && (e.tag.num == UTCTime || e.tag.num == GeneralizedTime)) { 860 pick v := e.val { 861 String => 862 return (1, v.s); 863 } 864 } 865 return (0, nil); 866} 867 868# Return printable error string for code ecode. 869# i is position where error is first noted. 870# n is the end of the passed data: if i!=n then 871# we didn't use all the data and an error should 872# be returned about that. 873errstr(ecode, i, n: int) : string 874{ 875 if(ecode == OK && i == n) 876 return ""; 877 err := "BER decode: "; 878 case ecode { 879 OK => 880 err += "OK"; 881 ESHORT => 882 err += "need more data"; 883 ETOOBIG => 884 err += "value exceeds implementation limit"; 885 EVALLEN => 886 err += "value has wrong length"; 887 ECONSTR => 888 err += "value is constructed, should be primitive"; 889 EPRIM => 890 err += "value is primitive"; 891 EINVAL => 892 err += "value encoding invalid"; 893 * => 894 err += "unknown error " + string ecode; 895 } 896 if(err == "" && i != n) 897 err += "extra data"; 898 err += " at byte " + string i; 899 return err; 900} 901 902# Printing functions, for debugging 903 904Tag.tostring(t: self Tag) : string 905{ 906 ans := ""; 907 snum := string t.num; 908 if(t.class == Universal) { 909 case t.num { 910 BOOLEAN => ans = "BOOLEAN"; 911 INTEGER => ans = "INTEGER"; 912 BIT_STRING => ans = "BIT STRING"; 913 OCTET_STRING => ans = "OCTET STRING"; 914 NULL => ans = "NULL"; 915 OBJECT_ID => ans = "OBJECT IDENTIFER"; 916 ObjectDescriptor => ans = "OBJECT_DES"; 917 EXTERNAL => ans = "EXTERNAL"; 918 REAL => ans = "REAL"; 919 ENUMERATED => ans = "ENUMERATED"; 920 EMBEDDED_PDV => ans = "EMBEDDED PDV"; 921 SEQUENCE => ans = "SEQUENCE"; 922 SET => ans = "SET"; 923 NumericString => ans = "NumericString"; 924 PrintableString => ans = "PrintableString"; 925 TeletexString => ans = "TeletexString"; 926 VideotexString => ans = "VideotexString"; 927 IA5String => ans = "IA5String"; 928 UTCTime => ans = "UTCTime"; 929 GeneralizedTime => ans = "GeneralizedTime"; 930 GraphicString => ans = "GraphicString"; 931 VisibleString => ans = "VisibleString"; 932 GeneralString => ans = "GeneralString"; 933 UniversalString => ans = "UniversalString"; 934 BMPString => ans = "BMPString"; 935 * => ans = "UNIVERSAL " + snum; 936 } 937 } 938 else { 939 case t.class { 940 Application => 941 ans = "APPLICATION " + snum; 942 Context => 943 ans = "CONTEXT "+ snum; 944 Private => 945 ans = "PRIVATE " + snum; 946 } 947 } 948 return ans; 949} 950 951Elem.tostring(e: self ref Elem) : string 952{ 953 return estring(e, ""); 954} 955 956Value.tostring(v: self ref Value) : string 957{ 958 return vstring(v, ""); 959} 960 961estring(e: ref Elem, indent: string) : string 962{ 963 return indent + e.tag.tostring() + " " + vstring(e.val, indent); 964} 965 966vstring(val: ref Value, indent: string) : string 967{ 968 ans := ""; 969 pick v := val { 970 Bool or Int => 971 ans += string v.v; 972 Octets or BigInt or Real or Other => 973 ans += bastring(v.bytes, indent + "\t"); 974 BitString => 975 ans += " bits (unused " +string v.unusedbits + ")" + bastring(v.bits, indent + "\t"); 976 Null or EOC => 977 ; 978 ObjId => 979 ans += v.id.tostring(); 980 String => 981 ans += "\"" + v.s + "\""; 982 Seq or Set => 983 ans += "{\n"; 984 newindent := indent + "\t"; 985 l := v.l; 986 while(l != nil) { 987 if(ans[len ans-1] != '\n') 988 ans[len ans] = '\n'; 989 ans += estring(hd l, newindent); 990 l = tl l; 991 } 992 if(ans[len ans-1] != '\n') 993 ans[len ans] = '\n'; 994 ans += indent + "}"; 995 } 996 return ans; 997} 998 999bastring(a: array of byte, indent: string) : string 1000{ 1001 if(sys == nil) 1002 sys = load Sys Sys->PATH; 1003 ans := indent; 1004 nlindent := "\n" + indent; 1005 for(i := 0; i < len a; i++) { 1006 if(i < len a - 1 && i%10 == 0) 1007 ans += nlindent ; 1008 ans += sys->sprint("%2x ", int a[i]); 1009 } 1010 return ans; 1011} 1012 1013Oid.tostring(o: self ref Oid) : string 1014{ 1015 ans := ""; 1016 for(i := 0; i < len o.nums; i++) { 1017 ans += string o.nums[i]; 1018 if(i < len o.nums - 1) 1019 ans[len ans] = '.'; 1020 } 1021 return ans; 1022} 1023 1024print_elem(e: ref Elem) 1025{ 1026 s := e.tostring(); 1027 a := array of byte s; 1028 sys->write(sys->fildes(1), a, len a); 1029 sys->print("\n"); 1030} 1031