asn1.js (221246B)
1 /* 2 * Copyright (c) 2014, GMO GlobalSign 3 * Copyright (c) 2015, Peculiar Ventures 4 * All rights reserved. 5 * 6 * Author 2014-2015, Yury Strozhevsky <www.strozhevsky.com>. 7 * 8 * Redistribution and use in source and binary forms, with or without modification, 9 * are permitted provided that the following conditions are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright notice, 12 * this list of conditions and the following disclaimer. 13 * 14 * 2. Redistributions in binary form must reproduce the above copyright notice, 15 * this list of conditions and the following disclaimer in the documentation 16 * and/or other materials provided with the distribution. 17 * 18 * 3. Neither the name of the copyright holder nor the names of its contributors 19 * may be used to endorse or promote products derived from this software without 20 * specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 26 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 28 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 31 * OF SUCH DAMAGE. 32 * 33 */ 34 ( 35 function(in_window) 36 { 37 //************************************************************************************** 38 // #region Declaration of global variables 39 //************************************************************************************** 40 // #region "org" namespace 41 if(typeof in_window.org === "undefined") 42 in_window.org = {}; 43 else 44 { 45 if(typeof in_window.org !== "object") 46 throw new Error("Name org already exists and it's not an object"); 47 } 48 // #endregion 49 50 // #region "org.pkijs" namespace 51 if(typeof in_window.org.pkijs === "undefined") 52 in_window.org.pkijs = {}; 53 else 54 { 55 if(typeof in_window.org.pkijs !== "object") 56 throw new Error("Name org.pkijs already exists and it's not an object" + " but " + (typeof in_window.org.pkijs)); 57 } 58 // #endregion 59 60 // #region "org.pkijs.asn1" namespace 61 if(typeof in_window.org.pkijs.asn1 === "undefined") 62 in_window.org.pkijs.asn1 = {}; 63 else 64 { 65 if(typeof in_window.org.pkijs.asn1 !== "object") 66 throw new Error("Name org.pkijs.asn1 already exists and it's not an object" + " but " + (typeof in_window.org.pkijs.asn1)); 67 } 68 // #endregion 69 70 // #region "local" namespace 71 var local = {}; 72 // #endregion 73 //************************************************************************************** 74 // #endregion 75 //************************************************************************************** 76 // #region Aux-functions 77 //************************************************************************************** 78 function util_frombase(input_buffer, input_base) 79 { 80 /// <summary>Convert number from 2^base to 2^10</summary> 81 /// <param name="input_buffer" type="Uint8Array">Array of bytes representing the number to convert</param> 82 /// <param name="input_base" type="Number">The base of initial number</param> 83 84 var result = 0; 85 86 for(var i = (input_buffer.length - 1); i >= 0; i-- ) 87 result += input_buffer[(input_buffer.length - 1) - i] * Math.pow(2, input_base * i); 88 89 return result; 90 } 91 //************************************************************************************** 92 function util_tobase(value, base, reserved) 93 { 94 /// <summary>Convert number from 2^10 to 2^base</summary> 95 /// <param name="value" type="Number">The number to convert</param> 96 /// <param name="base" type="Number">The base for 2^base</param> 97 /// <param name="reserved" type="Number">Pre-defined number of bytes in output array (-1 = limited by function itself)</param> 98 99 reserved = reserved || (-1); 100 101 var result = 0; 102 var biggest = Math.pow(2, base); 103 104 for(var i = 1; i < 8; i++) 105 { 106 if(value < biggest) 107 { 108 var ret_buf; 109 110 if( reserved < 0 ) 111 { 112 ret_buf = new ArrayBuffer(i); 113 result = i; 114 } 115 else 116 { 117 if(reserved < i) 118 return (new ArrayBuffer(0)); 119 120 ret_buf = new ArrayBuffer(reserved); 121 122 result = reserved; 123 } 124 125 var ret_view = new Uint8Array(ret_buf); 126 127 for(var j = ( i - 1 ); j >= 0; j-- ) 128 { 129 var basis = Math.pow(2, j * base); 130 131 ret_view[ result - j - 1 ] = Math.floor( value / basis ); 132 value -= ( ret_view[ result - j - 1 ] ) * basis; 133 } 134 135 return ret_buf; 136 } 137 138 biggest *= Math.pow(2, base); 139 } 140 } 141 //************************************************************************************** 142 function util_encode_tc(value) 143 { 144 /// <summary>Encode integer value to "two complement" format</summary> 145 /// <param name="value" type="Number">Value to encode</param> 146 147 var mod_value = (value < 0) ? (value * (-1)) : value; 148 var big_int = 128; 149 150 for(var i = 1; i < 8; i++) 151 { 152 if( mod_value <= big_int ) 153 { 154 if( value < 0 ) 155 { 156 var small_int = big_int - mod_value; 157 158 var ret_buf = util_tobase( small_int, 8, i ); 159 var ret_view = new Uint8Array(ret_buf); 160 161 ret_view[ 0 ] |= 0x80; 162 163 return ret_buf; 164 } 165 else 166 { 167 var ret_buf = util_tobase( mod_value, 8, i ); 168 var ret_view = new Uint8Array(ret_buf); 169 170 if( ret_view[ 0 ] & 0x80 ) 171 { 172 var temp_buf = util_copybuf(ret_buf); 173 var temp_view = new Uint8Array(temp_buf); 174 175 ret_buf = new ArrayBuffer( ret_buf.byteLength + 1 ); 176 ret_view = new Uint8Array(ret_buf); 177 178 for(var k = 0; k < temp_buf.byteLength; k++) 179 ret_view[k + 1] = temp_view[k]; 180 181 ret_view[0] = 0x00; 182 } 183 184 return ret_buf; 185 } 186 } 187 188 big_int *= Math.pow(2, 8); 189 } 190 191 return (new ArrayBuffer(0)); 192 } 193 //************************************************************************************** 194 function util_decode_tc() 195 { 196 /// <summary>Decoding of "two complement" values</summary> 197 /// <remarks>The function must be called in scope of instance of "hex_block" class ("value_hex" and "warnings" properties must be present)</remarks> 198 199 var buf = new Uint8Array(this.value_hex); 200 201 if(this.value_hex.byteLength >= 2) 202 { 203 var condition_1 = (buf[0] == 0xFF) && (buf[1] & 0x80); 204 var condition_2 = (buf[0] == 0x00) && ((buf[1] & 0x80) == 0x00); 205 206 if(condition_1 || condition_2) 207 this.warnings.push("Needlessly long format"); 208 } 209 210 // #region Create big part of the integer 211 var big_int_buffer = new ArrayBuffer(this.value_hex.byteLength); 212 var big_int_view = new Uint8Array(big_int_buffer); 213 for(var i = 0; i < this.value_hex.byteLength; i++) 214 big_int_view[i] = 0; 215 216 big_int_view[0] = (buf[0] & 0x80); // mask only the biggest bit 217 218 var big_int = util_frombase(big_int_view, 8); 219 // #endregion 220 221 // #region Create small part of the integer 222 var small_int_buffer = new ArrayBuffer(this.value_hex.byteLength); 223 var small_int_view = new Uint8Array(small_int_buffer); 224 for(var j = 0; j < this.value_hex.byteLength; j++) 225 small_int_view[j] = buf[j]; 226 227 small_int_view[0] &= 0x7F; // mask biggest bit 228 229 var small_int = util_frombase(small_int_view, 8); 230 // #endregion 231 232 return (small_int - big_int); 233 } 234 //************************************************************************************** 235 function util_copybuf(input_buffer) 236 { 237 /// <summary>Creating a copy of input ArrayBuffer</summary> 238 /// <param name="input_buffer" type="ArrayBuffer">ArrayBuffer for coping</param> 239 240 if(check_buffer_params(input_buffer, 0, input_buffer.byteLength) === false) 241 return (new ArrayBuffer(0)); 242 243 var input_view = new Uint8Array(input_buffer); 244 245 var ret_buf = new ArrayBuffer(input_buffer.byteLength); 246 var ret_view = new Uint8Array(ret_buf); 247 248 for(var i = 0; i < input_buffer.byteLength; i++) 249 ret_view[i] = input_view[i]; 250 251 return ret_buf; 252 } 253 //************************************************************************************** 254 function util_copybuf_offset(input_buffer, input_offset, input_length) 255 { 256 /// <summary>Creating a copy of input ArrayBuffer</summary> 257 /// <param name="input_buffer" type="ArrayBuffer">ArrayBuffer for coping</param> 258 259 if(check_buffer_params(input_buffer, input_offset, input_length) === false) 260 return (new ArrayBuffer(0)); 261 262 var input_view = new Uint8Array(input_buffer, input_offset, input_length); 263 264 var ret_buf = new ArrayBuffer(input_length); 265 var ret_view = new Uint8Array(ret_buf); 266 267 for(var i = 0; i < input_length; i++) 268 ret_view[i] = input_view[i]; 269 270 return ret_buf; 271 } 272 //************************************************************************************** 273 function util_concatbuf(input_buf1, input_buf2) 274 { 275 /// <summary>Concatenate two ArrayBuffers</summary> 276 /// <param name="input_buf1" type="ArrayBuffer">First ArrayBuffer (first part of concatenated array)</param> 277 /// <param name="input_buf2" type="ArrayBuffer">Second ArrayBuffer (second part of concatenated array)</param> 278 279 var input_view1 = new Uint8Array(input_buf1); 280 var input_view2 = new Uint8Array(input_buf2); 281 282 var ret_buf = new ArrayBuffer(input_buf1.byteLength + input_buf2.byteLength); 283 var ret_view = new Uint8Array(ret_buf); 284 285 for(var i = 0; i < input_buf1.byteLength; i++) 286 ret_view[i] = input_view1[i]; 287 288 for(var j = 0; j < input_buf2.byteLength; j++) 289 ret_view[input_buf1.byteLength + j] = input_view2[j]; 290 291 return ret_buf; 292 } 293 //************************************************************************************** 294 function check_buffer_params(input_buffer, input_offset, input_length) 295 { 296 if((input_buffer instanceof ArrayBuffer) === false) 297 { 298 this.error = "Wrong parameter: input_buffer must be \"ArrayBuffer\""; 299 return false; 300 } 301 302 if(input_buffer.byteLength === 0) 303 { 304 this.error = "Wrong parameter: input_buffer has zero length"; 305 return false; 306 } 307 308 if(input_offset < 0) 309 { 310 this.error = "Wrong parameter: input_offset less than zero"; 311 return false; 312 } 313 314 if(input_length < 0) 315 { 316 this.error = "Wrong parameter: input_length less than zero"; 317 return false; 318 } 319 320 if((input_buffer.byteLength - input_offset - input_length) < 0) 321 { 322 this.error = "End of input reached before message was fully decoded (inconsistent offset and length values)"; 323 return false; 324 } 325 326 return true; 327 } 328 //************************************************************************************** 329 function to_hex_codes(input_buffer, input_offset, input_lenght) 330 { 331 if(check_buffer_params(input_buffer, input_offset, input_lenght) === false) 332 return ""; 333 334 var result = ""; 335 336 var int_buffer = new Uint8Array(input_buffer, input_offset, input_lenght); 337 338 for(var i = 0; i < int_buffer.length; i++) 339 { 340 var str = int_buffer[i].toString(16).toUpperCase(); 341 result = result + ((str.length === 1) ? " 0" : " ") + str; 342 } 343 344 return result; 345 } 346 //************************************************************************************** 347 // #endregion 348 //************************************************************************************** 349 // #region Declaration of base block class 350 //************************************************************************************** 351 local.base_block = 352 function() 353 { 354 /// <summary>General class of all ASN.1 blocks</summary> 355 356 if(arguments[0] instanceof Object) 357 { 358 this.block_length = in_window.org.pkijs.getValue(arguments[0], "block_length", 0); 359 this.error = in_window.org.pkijs.getValue(arguments[0], "error", new String()); 360 this.warnings = in_window.org.pkijs.getValue(arguments[0], "warnings", new Array()); 361 if("value_before_decode" in arguments[0]) 362 this.value_before_decode = util_copybuf(arguments[0].value_before_decode); 363 else 364 this.value_before_decode = new ArrayBuffer(0); 365 } 366 else 367 { 368 this.block_length = 0; 369 this.error = new String(); 370 this.warnings = new Array(); 371 /// <field>Copy of the value of incoming ArrayBuffer done before decoding</field> 372 this.value_before_decode = new ArrayBuffer(0); 373 } 374 }; 375 //************************************************************************************** 376 local.base_block.prototype.block_name = 377 function() 378 { 379 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 380 381 return "base_block"; 382 }; 383 //************************************************************************************** 384 local.base_block.prototype.toJSON = 385 function() 386 { 387 /// <summary>Convertion for the block to JSON object</summary> 388 389 return { 390 block_name: local.base_block.prototype.block_name.call(this), 391 block_length: this.block_length, 392 error: this.error, 393 warnings: this.warnings, 394 value_before_decode: in_window.org.pkijs.bufferToHexCodes(this.value_before_decode, 0, this.value_before_decode.byteLength) 395 }; 396 }; 397 //************************************************************************************** 398 // #endregion 399 //************************************************************************************** 400 // #region Declaration of hex block class 401 //************************************************************************************** 402 local.hex_block = 403 function() 404 { 405 /// <summary>Descendant of "base_block" with internal ArrayBuffer. Need to have it in case it is not possible to store ASN.1 value in native formats</summary> 406 407 local.base_block.call(this, arguments[0]); 408 409 if(arguments[0] instanceof Object) 410 { 411 this.is_hex_only = in_window.org.pkijs.getValue(arguments[0], "is_hex_only", false); 412 if("value_hex" in arguments[0]) 413 this.value_hex = util_copybuf(arguments[0].value_hex); 414 else 415 this.value_hex = new ArrayBuffer(0); 416 } 417 else 418 { 419 this.is_hex_only = false; 420 this.value_hex = new ArrayBuffer(0); 421 } 422 }; 423 //************************************************************************************** 424 local.hex_block.prototype = new local.base_block(); 425 local.hex_block.constructor = local.hex_block; 426 //************************************************************************************** 427 local.hex_block.prototype.block_name = 428 function() 429 { 430 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 431 432 return "hex_block"; 433 }; 434 //************************************************************************************** 435 local.hex_block.prototype.fromBER = 436 function(input_buffer, input_offset, input_length) 437 { 438 /// <summary>Base function for converting block from BER encoded array of bytes</summary> 439 /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param> 440 /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param> 441 /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param> 442 443 // #region Basic check for parameters 444 if(check_buffer_params.call(this, input_buffer, input_offset, input_length) === false) 445 return (-1); 446 // #endregion 447 448 // #region Getting Uint8Array from ArrayBuffer 449 var int_buffer = new Uint8Array(input_buffer, input_offset, input_length); 450 // #endregion 451 452 // #region Initial checks 453 if(int_buffer.length == 0) 454 { 455 this.warnings.push("Zero buffer length"); 456 return input_offset; 457 } 458 // #endregion 459 460 // #region Copy input buffer to internal buffer 461 this.value_hex = new ArrayBuffer(input_length); 462 var view = new Uint8Array(this.value_hex); 463 464 for(var i = 0; i < int_buffer.length; i++) 465 view[i] = int_buffer[i]; 466 // #endregion 467 468 this.block_length = input_length; 469 470 return (input_offset + input_length); 471 }; 472 //************************************************************************************** 473 local.hex_block.prototype.toBER = 474 function(size_only) 475 { 476 /// <summary>Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)</summary> 477 /// <param name="size_only" type="Boolean">Flag that we need only a size of encoding, not a real array of bytes</param> 478 479 if(typeof size_only === "undefined") 480 size_only = false; 481 482 if(this.is_hex_only !== true) 483 { 484 this.error = "Flag \"is_hex_only\" is not set, abort"; 485 return (new ArrayBuffer(0)); 486 } 487 488 var ret_buf = new ArrayBuffer(this.value_hex.byteLength); 489 490 if(size_only === true) 491 return ret_buf; 492 493 var ret_view = new Uint8Array(ret_buf); 494 var cur_view = new Uint8Array(this.value_hex); 495 496 for(var i = 0; i < cur_view.length; i++) 497 ret_view[i] = cur_view[i]; 498 499 return ret_buf; 500 }; 501 //************************************************************************************** 502 local.hex_block.prototype.toJSON = 503 function() 504 { 505 /// <summary>Convertion for the block to JSON object</summary> 506 507 var _object = local.base_block.prototype.toJSON.call(this); 508 509 _object.block_name = local.hex_block.prototype.block_name.call(this); 510 _object.is_hex_only = this.is_hex_only; 511 _object.value_hex = in_window.org.pkijs.bufferToHexCodes(this.value_hex, 0, this.value_hex.byteLength); 512 513 return _object; 514 }; 515 //************************************************************************************** 516 // #endregion 517 //************************************************************************************** 518 // #region Declaration of identification block class 519 //************************************************************************************** 520 local.identification_block = 521 function() 522 { 523 /// <summary>Base class of ASN.1 "identification block"</summary> 524 525 local.hex_block.call(this, arguments[0]); 526 527 this.tag_class = (-1); 528 this.tag_number = (-1); 529 this.is_constructed = false; 530 531 if(arguments[0] instanceof Object) 532 { 533 if("id_block" in arguments[0]) 534 { 535 // #region Properties from hex_block class 536 this.is_hex_only = in_window.org.pkijs.getValue(arguments[0].id_block, "is_hex_only", false); 537 this.value_hex = in_window.org.pkijs.getValue(arguments[0].id_block, "value_hex", new ArrayBuffer(0)); 538 // #endregion 539 540 this.tag_class = in_window.org.pkijs.getValue(arguments[0].id_block, "tag_class", (-1)); 541 this.tag_number = in_window.org.pkijs.getValue(arguments[0].id_block, "tag_number", (-1)); 542 this.is_constructed = in_window.org.pkijs.getValue(arguments[0].id_block, "is_constructed", false); 543 } 544 } 545 }; 546 //************************************************************************************** 547 local.identification_block.prototype = new local.hex_block(); 548 local.identification_block.constructor = local.identification_block; 549 //************************************************************************************** 550 local.identification_block.prototype.block_name = 551 function() 552 { 553 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 554 555 return "identification_block"; 556 }; 557 //************************************************************************************** 558 local.identification_block.prototype.toBER = 559 function(size_only) 560 { 561 /// <summary>Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)</summary> 562 /// <param name="size_only" type="Boolean">Flag that we need only a size of encoding, not a real array of bytes</param> 563 564 if(typeof size_only === "undefined") 565 size_only = false; 566 567 var first_octet = 0; 568 569 switch(this.tag_class) 570 { 571 case 1: 572 first_octet |= 0x00; // UNIVERSAL 573 break; 574 case 2: 575 first_octet |= 0x40; // APPLICATION 576 break; 577 case 3: 578 first_octet |= 0x80; // CONTEXT-SPECIFIC 579 break; 580 case 4: 581 first_octet |= 0xC0; // PRIVATE 582 break; 583 default: 584 this.error = "Unknown tag class"; 585 return (new ArrayBuffer(0)); 586 } 587 588 if(this.is_constructed) 589 first_octet |= 0x20; 590 591 if((this.tag_number < 31) && (!this.is_hex_only)) 592 { 593 var ret_buf = new ArrayBuffer(1); 594 var ret_view = new Uint8Array(ret_buf); 595 596 if(!size_only) 597 { 598 var number = this.tag_number; 599 number &= 0x1F; 600 first_octet |= number; 601 602 ret_view[0] = first_octet; 603 } 604 605 return ret_buf; 606 } 607 else 608 { 609 if(this.is_hex_only === false) 610 { 611 var encoded_buf = util_tobase(this.tag_number, 7); 612 var encoded_view = new Uint8Array(encoded_buf); 613 var size = encoded_buf.byteLength; 614 615 var ret_buf = new ArrayBuffer(size + 1); 616 var ret_view = new Uint8Array(ret_buf); 617 618 ret_view[0] = (first_octet | 0x1F); 619 620 if(!size_only) 621 { 622 for(var i = 0; i < (size - 1) ; i++) 623 ret_view[i + 1] = encoded_view[i] | 0x80; 624 625 ret_view[size] = encoded_view[size - 1]; 626 } 627 628 return ret_buf; 629 } 630 else 631 { 632 var ret_buf = new ArrayBuffer(this.value_hex.byteLength + 1); 633 var ret_view = new Uint8Array(ret_buf); 634 635 ret_view[0] = (first_octet | 0x1F); 636 637 if(size_only === false) 638 { 639 var cur_view = new Uint8Array(this.value_hex); 640 641 for(var i = 0; i < (cur_view.length - 1); i++) 642 ret_view[i + 1] = cur_view[i] | 0x80; 643 644 ret_view[this.value_hex.byteLength] = cur_view[cur_view.length - 1]; 645 } 646 647 return ret_buf; 648 } 649 } 650 }; 651 //************************************************************************************** 652 local.identification_block.prototype.fromBER = 653 function(input_buffer, input_offset, input_length) 654 { 655 /// <summary>Base function for converting block from BER encoded array of bytes</summary> 656 /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param> 657 /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param> 658 /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param> 659 660 // #region Basic check for parameters 661 if(check_buffer_params.call(this, input_buffer, input_offset, input_length) === false) 662 return (-1); 663 // #endregion 664 665 // #region Getting Uint8Array from ArrayBuffer 666 var int_buffer = new Uint8Array(input_buffer, input_offset, input_length); 667 // #endregion 668 669 // #region Initial checks 670 if(int_buffer.length == 0) 671 { 672 this.error = "Zero buffer length"; 673 return (-1); 674 } 675 // #endregion 676 677 // #region Find tag class 678 var tag_class_mask = int_buffer[0] & 0xC0; 679 680 switch(tag_class_mask) 681 { 682 case 0x00: 683 this.tag_class = (1); // UNIVERSAL 684 break; 685 case 0x40: 686 this.tag_class = (2); // APPLICATION 687 break; 688 case 0x80: 689 this.tag_class = (3); // CONTEXT-SPECIFIC 690 break; 691 case 0xC0: 692 this.tag_class = (4); // PRIVATE 693 break; 694 default: 695 this.error = "Unknown tag class"; 696 return ( -1 ); 697 } 698 // #endregion 699 700 // #region Find it's constructed or not 701 this.is_constructed = (int_buffer[0] & 0x20) == 0x20; 702 // #endregion 703 704 // #region Find tag number 705 this.is_hex_only = false; 706 707 var tag_number_mask = int_buffer[0] & 0x1F; 708 709 // #region Simple case (tag number < 31) 710 if(tag_number_mask != 0x1F) 711 { 712 this.tag_number = (tag_number_mask); 713 this.block_length = 1; 714 } 715 // #endregion 716 // #region Tag number bigger or equal to 31 717 else 718 { 719 var count = 1; 720 721 this.value_hex = new ArrayBuffer(255); 722 var tag_number_buffer_max_length = 255; 723 var int_tag_number_buffer = new Uint8Array(this.value_hex); 724 725 while(int_buffer[count] & 0x80) 726 { 727 int_tag_number_buffer[count - 1] = int_buffer[count] & 0x7F; 728 count++; 729 730 if(count >= int_buffer.length) 731 { 732 this.error = "End of input reached before message was fully decoded"; 733 return (-1); 734 } 735 736 // #region In case if tag number length is greater than 255 bytes (rare but possible case) 737 if(count == tag_number_buffer_max_length) 738 { 739 tag_number_buffer_max_length += 255; 740 741 var temp_buffer = new ArrayBuffer(tag_number_buffer_max_length); 742 var temp_buffer_view = new Uint8Array(temp_buffer); 743 744 for(var i = 0; i < int_tag_number_buffer.length; i++) 745 temp_buffer_view[i] = int_tag_number_buffer[i]; 746 747 this.value_hex = new ArrayBuffer(tag_number_buffer_max_length); 748 int_tag_number_buffer = new Uint8Array(this.value_hex); 749 } 750 // #endregion 751 } 752 753 this.block_length = (count + 1); 754 int_tag_number_buffer[count - 1] = int_buffer[count] & 0x7F; // Write last byte to buffer 755 756 // #region Cut buffer 757 var temp_buffer = new ArrayBuffer(count); 758 var temp_buffer_view = new Uint8Array(temp_buffer); 759 for(var i = 0; i < count; i++) 760 temp_buffer_view[i] = int_tag_number_buffer[i]; 761 762 this.value_hex = new ArrayBuffer(count); 763 int_tag_number_buffer = new Uint8Array(this.value_hex); 764 int_tag_number_buffer.set(temp_buffer_view); 765 // #endregion 766 767 // #region Try to convert long tag number to short form 768 if(this.block_length <= 9) 769 this.tag_number = util_frombase(int_tag_number_buffer, 7); 770 else 771 { 772 this.is_hex_only = true; 773 this.warnings.push("Tag too long, represented as hex-coded"); 774 } 775 // #endregion 776 } 777 // #endregion 778 // #endregion 779 780 // #region Check if constructed encoding was using for primitive type 781 if(((this.tag_class == 1)) && 782 (this.is_constructed)) 783 { 784 switch(this.tag_number) 785 { 786 case 1: // BOOLEAN 787 case 2: // REAL 788 case 5: // NULL 789 case 6: // OBJECT IDENTIFIER 790 case 9: // REAL 791 case 14: // TIME 792 case 23: 793 case 24: 794 case 31: 795 case 32: 796 case 33: 797 case 34: 798 this.error = "Constructed encoding used for primitive type"; 799 return (-1); 800 default: 801 ; 802 } 803 } 804 // #endregion 805 806 return ( input_offset + this.block_length ); // Return current offset in input buffer 807 }; 808 //************************************************************************************** 809 local.identification_block.prototype.toJSON = 810 function() 811 { 812 /// <summary>Convertion for the block to JSON object</summary> 813 814 var _object = local.hex_block.prototype.toJSON.call(this); 815 816 _object.block_name = local.identification_block.prototype.block_name.call(this); 817 _object.tag_class = this.tag_class; 818 _object.tag_number = this.tag_number; 819 _object.is_constructed = this.is_constructed; 820 821 return _object; 822 }; 823 //************************************************************************************** 824 // #endregion 825 //************************************************************************************** 826 // #region Declaration of length block class 827 //************************************************************************************** 828 local.length_block = 829 function() 830 { 831 /// <summary>Base class of ASN.1 "length block"</summary> 832 833 local.base_block.call(this, arguments[0]); 834 835 this.is_indefinite_form = false; 836 this.long_form_used = false; 837 this.length = (0); 838 839 if(arguments[0] instanceof Object) 840 { 841 if("len_block" in arguments[0]) 842 { 843 this.is_indefinite_form = in_window.org.pkijs.getValue(arguments[0].len_block, "is_indefinite_form", false); 844 this.long_form_used = in_window.org.pkijs.getValue(arguments[0].len_block, "long_form_used", false); 845 this.length = in_window.org.pkijs.getValue(arguments[0].len_block, "length", 0); 846 } 847 } 848 }; 849 //************************************************************************************** 850 local.length_block.prototype = new local.base_block(); 851 local.length_block.constructor = local.length_block; 852 //************************************************************************************** 853 local.length_block.prototype.block_name = 854 function() 855 { 856 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 857 858 return "length_block"; 859 }; 860 //************************************************************************************** 861 local.length_block.prototype.fromBER = 862 function(input_buffer, input_offset, input_length) 863 { 864 /// <summary>Base function for converting block from BER encoded array of bytes</summary> 865 /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param> 866 /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param> 867 /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param> 868 869 // #region Basic check for parameters 870 if(check_buffer_params.call(this, input_buffer, input_offset, input_length) === false) 871 return (-1); 872 // #endregion 873 874 // #region Getting Uint8Array from ArrayBuffer 875 var int_buffer = new Uint8Array(input_buffer, input_offset, input_length); 876 // #endregion 877 878 // #region Initial checks 879 if(int_buffer.length == 0) 880 { 881 this.error = "Zero buffer length"; 882 return (-1); 883 } 884 885 if(int_buffer[0] == 0xFF) 886 { 887 this.error = "Length block 0xFF is reserved by standard"; 888 return (-1); 889 } 890 // #endregion 891 892 // #region Check for length form type 893 this.is_indefinite_form = int_buffer[0] == 0x80; 894 // #endregion 895 896 // #region Stop working in case of indefinite length form 897 if(this.is_indefinite_form == true) 898 { 899 this.block_length = 1; 900 return (input_offset + this.block_length); 901 } 902 // #endregion 903 904 // #region Check is long form of length encoding using 905 this.long_form_used = !!(int_buffer[0] & 0x80); 906 // #endregion 907 908 // #region Stop working in case of short form of length value 909 if(this.long_form_used == false) 910 { 911 this.length = (int_buffer[0]); 912 this.block_length = 1; 913 return (input_offset + this.block_length); 914 } 915 // #endregion 916 917 // #region Calculate length value in case of long form 918 var count = int_buffer[0] & 0x7F; 919 920 if(count > 8) // Too big length value 921 { 922 this.error = "Too big integer"; 923 return (-1); 924 } 925 926 if((count + 1) > int_buffer.length) 927 { 928 this.error = "End of input reached before message was fully decoded"; 929 return (-1); 930 } 931 932 var length_buffer_view = new Uint8Array(count); 933 934 for(var i = 0; i < count; i++) 935 length_buffer_view[i] = int_buffer[i + 1]; 936 937 if(length_buffer_view[count - 1] == 0x00) 938 this.warnings.push("Needlessly long encoded length"); 939 940 this.length = util_frombase(length_buffer_view, 8); 941 942 if(this.long_form_used && (this.length <= 127)) 943 this.warnings.push("Unneccesary usage of long length form"); 944 945 this.block_length = count + 1; 946 // #endregion 947 948 return (input_offset + this.block_length); // Return current offset in input buffer 949 }; 950 //************************************************************************************** 951 local.length_block.prototype.toBER = 952 function(size_only) 953 { 954 /// <summary>Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)</summary> 955 /// <param name="size_only" type="Boolean">Flag that we need only a size of encoding, not a real array of bytes</param> 956 957 if(typeof size_only === "undefined") 958 size_only = false; 959 960 if(this.length > 127) 961 this.long_form_used = true; 962 963 if(this.is_indefinite_form) 964 { 965 var ret_buf = new ArrayBuffer(1); 966 967 if(size_only === false) 968 { 969 var ret_view = new Uint8Array(ret_buf); 970 ret_view[0] = 0x80; 971 } 972 973 return ret_buf; 974 } 975 976 if(this.long_form_used === true) 977 { 978 var encoded_buf = util_tobase(this.length, 8); 979 980 if(encoded_buf.byteLength > 127) 981 { 982 this.error = "Too big length"; 983 return (new ArrayBuffer(0)); 984 } 985 986 var ret_buf = new ArrayBuffer(encoded_buf.byteLength + 1); 987 988 if(size_only === true) 989 return ret_buf; 990 991 var encoded_view = new Uint8Array(encoded_buf); 992 var ret_view = new Uint8Array(ret_buf); 993 994 ret_view[0] = encoded_buf.byteLength | 0x80; 995 996 for(var i = 0; i < encoded_buf.byteLength; i++) 997 ret_view[i + 1] = encoded_view[i]; 998 999 return ret_buf; 1000 } 1001 else 1002 { 1003 var ret_buf = new ArrayBuffer(1); 1004 1005 if(size_only === false) 1006 { 1007 var ret_view = new Uint8Array(ret_buf); 1008 1009 ret_view[0] = this.length; 1010 } 1011 1012 return ret_buf; 1013 } 1014 1015 return (new ArrayBuffer(0)); 1016 }; 1017 //************************************************************************************** 1018 local.length_block.prototype.toJSON = 1019 function() 1020 { 1021 /// <summary>Convertion for the block to JSON object</summary> 1022 1023 var _object = local.base_block.prototype.toJSON.call(this); 1024 1025 _object.block_name = local.length_block.prototype.block_name.call(this); 1026 _object.is_indefinite_form = this.is_indefinite_form; 1027 _object.long_form_used = this.long_form_used; 1028 _object.length = this.length; 1029 1030 return _object; 1031 }; 1032 //************************************************************************************** 1033 // #endregion 1034 //************************************************************************************** 1035 // #region Declaration of value block class 1036 //************************************************************************************** 1037 local.value_block = 1038 function() 1039 { 1040 /// <summary>Generic class of ASN.1 "value block"</summary> 1041 local.base_block.call(this, arguments[0]); 1042 }; 1043 //************************************************************************************** 1044 local.value_block.prototype = new local.base_block(); 1045 local.value_block.constructor = local.value_block; 1046 //************************************************************************************** 1047 local.value_block.prototype.block_name = 1048 function() 1049 { 1050 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 1051 1052 return "value_block"; 1053 }; 1054 //************************************************************************************** 1055 local.value_block.prototype.toJSON = 1056 function() 1057 { 1058 /// <summary>Convertion for the block to JSON object</summary> 1059 1060 var _object = local.base_block.prototype.toJSON.call(this); 1061 1062 _object.block_name = local.value_block.prototype.block_name.call(this); 1063 1064 return _object; 1065 }; 1066 //************************************************************************************** 1067 // #endregion 1068 //************************************************************************************** 1069 // #region Declaration of basic ASN.1 block class 1070 //************************************************************************************** 1071 in_window.org.pkijs.asn1.ASN1_block = 1072 function() 1073 { 1074 /// <summary>Base class of ASN.1 block (identification block + length block + value block)</summary> 1075 1076 local.base_block.call(this, arguments[0]); 1077 1078 if(arguments[0] instanceof Object) 1079 { 1080 this.name = in_window.org.pkijs.getValue(arguments[0], "name", ""); 1081 this.optional = in_window.org.pkijs.getValue(arguments[0], "optional", false); 1082 1083 if("primitive_schema" in arguments[0]) 1084 this.primitive_schema = arguments[0].primitive_schema; 1085 } 1086 1087 this.id_block = new local.identification_block(arguments[0]); 1088 this.len_block = new local.length_block(arguments[0]); 1089 this.value_block = new local.value_block(arguments[0]); 1090 }; 1091 //************************************************************************************** 1092 in_window.org.pkijs.asn1.ASN1_block.prototype = new local.base_block(); 1093 in_window.org.pkijs.asn1.ASN1_block.constructor = in_window.org.pkijs.asn1.ASN1_block; 1094 //************************************************************************************** 1095 in_window.org.pkijs.asn1.ASN1_block.prototype.block_name = 1096 function() 1097 { 1098 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 1099 1100 return "ASN1_block"; 1101 }; 1102 //************************************************************************************** 1103 in_window.org.pkijs.asn1.ASN1_block.prototype.fromBER = 1104 function(input_buffer, input_offset, input_length) 1105 { 1106 /// <summary>Base function for converting block from BER encoded array of bytes</summary> 1107 /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param> 1108 /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param> 1109 /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param> 1110 1111 var result_offset = this.value_block.fromBER(input_buffer, input_offset, (this.len_block.is_indefinite_form == true) ? input_length : this.len_block.length); 1112 if(result_offset == (-1)) 1113 { 1114 this.error = this.value_block.error; 1115 return result_offset; 1116 } 1117 1118 if(this.id_block.error.length == 0) 1119 this.block_length += this.id_block.block_length; 1120 1121 if(this.len_block.error.length == 0) 1122 this.block_length += this.len_block.block_length; 1123 1124 if(this.value_block.error.length == 0) 1125 this.block_length += this.value_block.block_length; 1126 1127 return result_offset; 1128 }; 1129 //************************************************************************************** 1130 in_window.org.pkijs.asn1.ASN1_block.prototype.toBER = 1131 function(size_only) 1132 { 1133 /// <summary>Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)</summary> 1134 /// <param name="size_only" type="Boolean">Flag that we need only a size of encoding, not a real array of bytes</param> 1135 1136 if(typeof size_only === "undefined") 1137 size_only = false; 1138 1139 var ret_buf; 1140 1141 var id_block_buf = this.id_block.toBER(size_only); 1142 var value_block_size_buf = this.value_block.toBER(true); 1143 1144 this.len_block.length = value_block_size_buf.byteLength; 1145 var len_block_buf = this.len_block.toBER(size_only); 1146 1147 ret_buf = util_concatbuf(id_block_buf, len_block_buf); 1148 1149 var value_block_buf; 1150 1151 if(size_only === false) 1152 value_block_buf = this.value_block.toBER(size_only); 1153 else 1154 value_block_buf = new ArrayBuffer(this.len_block.length); 1155 1156 ret_buf = util_concatbuf(ret_buf, value_block_buf); 1157 1158 if(this.len_block.is_indefinite_form === true) 1159 { 1160 var indef_buf = new ArrayBuffer(2); 1161 1162 if(size_only === false) 1163 { 1164 var indef_view = new Uint8Array(indef_buf); 1165 1166 indef_view[0] = 0x00; 1167 indef_view[1] = 0x00; 1168 } 1169 1170 ret_buf = util_concatbuf(ret_buf, indef_buf); 1171 } 1172 1173 return ret_buf; 1174 }; 1175 //************************************************************************************** 1176 in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON = 1177 function() 1178 { 1179 /// <summary>Convertion for the block to JSON object</summary> 1180 1181 var _object = local.base_block.prototype.toJSON.call(this); 1182 1183 _object.block_name = in_window.org.pkijs.asn1.ASN1_block.prototype.block_name.call(this); 1184 _object.id_block = this.id_block.toJSON(); 1185 _object.len_block = this.len_block.toJSON(); 1186 _object.value_block = this.value_block.toJSON(); 1187 1188 if("name" in this) 1189 _object.name = this.name; 1190 if("optional" in this) 1191 _object.optional = this.optional; 1192 if("primitive_schema" in this) 1193 _object.primitive_schema = this.primitive_schema.toJSON(); 1194 1195 return _object; 1196 }; 1197 //************************************************************************************** 1198 // #endregion 1199 //************************************************************************************** 1200 // #region Declaration of basic block for all PRIMITIVE types 1201 //************************************************************************************** 1202 local.ASN1_PRIMITIVE_value_block = 1203 function() 1204 { 1205 /// <summary>Base class of ASN.1 value block for primitive values (non-constructive encoding)</summary> 1206 1207 local.value_block.call(this, arguments[0]); 1208 1209 if(arguments[0] instanceof Object) 1210 { 1211 // #region Variables from "hex_block" class 1212 if("value_hex" in arguments[0]) 1213 this.value_hex = util_copybuf(arguments[0].value_hex); 1214 else 1215 this.value_hex = new ArrayBuffer(0); 1216 1217 this.is_hex_only = in_window.org.pkijs.getValue(arguments[0], "is_hex_only", true); 1218 // #endregion 1219 } 1220 else 1221 { 1222 // #region Variables from "hex_block" class 1223 this.value_hex = new ArrayBuffer(0); 1224 this.is_hex_only = true; 1225 // #endregion 1226 } 1227 }; 1228 //************************************************************************************** 1229 local.ASN1_PRIMITIVE_value_block.prototype = new local.value_block(); 1230 local.ASN1_PRIMITIVE_value_block.constructor = local.ASN1_PRIMITIVE_value_block; 1231 //************************************************************************************** 1232 local.ASN1_PRIMITIVE_value_block.prototype.fromBER = 1233 function(input_buffer, input_offset, input_length) 1234 { 1235 /// <summary>Base function for converting block from BER encoded array of bytes</summary> 1236 /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param> 1237 /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param> 1238 /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param> 1239 1240 // #region Basic check for parameters 1241 if(check_buffer_params.call(this, input_buffer, input_offset, input_length) === false) 1242 return (-1); 1243 // #endregion 1244 1245 // #region Getting Uint8Array from ArrayBuffer 1246 var int_buffer = new Uint8Array(input_buffer, input_offset, input_length); 1247 // #endregion 1248 1249 // #region Initial checks 1250 if(int_buffer.length == 0) 1251 { 1252 this.warnings.push("Zero buffer length"); 1253 return input_offset; 1254 } 1255 // #endregion 1256 1257 // #region Copy input buffer into internal buffer 1258 this.value_hex = new ArrayBuffer(int_buffer.length); 1259 var value_hex_view = new Uint8Array(this.value_hex); 1260 1261 for(var i = 0; i < int_buffer.length; i++) 1262 value_hex_view[i] = int_buffer[i]; 1263 // #endregion 1264 1265 this.block_length = input_length; 1266 1267 return (input_offset + input_length); 1268 }; 1269 //************************************************************************************** 1270 local.ASN1_PRIMITIVE_value_block.prototype.toBER = 1271 function(size_only) 1272 { 1273 /// <summary>Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)</summary> 1274 /// <param name="size_only" type="Boolean">Flag that we need only a size of encoding, not a real array of bytes</param> 1275 1276 return util_copybuf(this.value_hex); 1277 }; 1278 //************************************************************************************** 1279 local.ASN1_PRIMITIVE_value_block.prototype.block_name = 1280 function() 1281 { 1282 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 1283 1284 return "ASN1_PRIMITIVE_value_block"; 1285 }; 1286 //************************************************************************************** 1287 local.ASN1_PRIMITIVE_value_block.prototype.toJSON = 1288 function() 1289 { 1290 /// <summary>Convertion for the block to JSON object</summary> 1291 1292 var _object = local.value_block.prototype.toJSON.call(this); 1293 1294 _object.block_name = local.ASN1_PRIMITIVE_value_block.prototype.block_name.call(this); 1295 _object.value_hex = in_window.org.pkijs.bufferToHexCodes(this.value_hex, 0, this.value_hex.byteLength); 1296 _object.is_hex_only = this.is_hex_only; 1297 1298 return _object; 1299 }; 1300 //************************************************************************************** 1301 in_window.org.pkijs.asn1.ASN1_PRIMITIVE = 1302 function() 1303 { 1304 /// <summary>Base class of ASN.1 block for primitive values (non-constructive encoding)</summary> 1305 1306 in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]); 1307 1308 this.id_block.is_constructed = false; 1309 this.value_block = new local.ASN1_PRIMITIVE_value_block(arguments[0]); 1310 }; 1311 //************************************************************************************** 1312 in_window.org.pkijs.asn1.ASN1_PRIMITIVE.prototype = new in_window.org.pkijs.asn1.ASN1_block(); 1313 in_window.org.pkijs.asn1.ASN1_PRIMITIVE.constructor = in_window.org.pkijs.asn1.ASN1_PRIMITIVE; 1314 //************************************************************************************** 1315 in_window.org.pkijs.asn1.ASN1_PRIMITIVE.prototype.block_name = 1316 function() 1317 { 1318 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 1319 1320 return "PRIMITIVE"; 1321 }; 1322 //************************************************************************************** 1323 in_window.org.pkijs.asn1.ASN1_PRIMITIVE.prototype.toJSON = 1324 function() 1325 { 1326 /// <summary>Convertion for the block to JSON object</summary> 1327 1328 var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this); 1329 1330 _object.block_name = in_window.org.pkijs.asn1.ASN1_PRIMITIVE.prototype.block_name.call(this); 1331 1332 return _object; 1333 }; 1334 //************************************************************************************** 1335 // #endregion 1336 //************************************************************************************** 1337 // #region Declaration of basic block for all CONSTRUCTED types 1338 //************************************************************************************** 1339 local.ASN1_CONSTRUCTED_value_block = 1340 function() 1341 { 1342 /// <summary>Base class of ASN.1 value block for constructive values (constructive encoding)</summary> 1343 1344 local.value_block.call(this, arguments[0]); 1345 1346 if(arguments[0] instanceof Object) 1347 { 1348 this.value = in_window.org.pkijs.getValue(arguments[0], "value", new Array()); 1349 this.is_indefinite_form = in_window.org.pkijs.getValue(arguments[0], "is_indefinite_form", false); 1350 } 1351 else 1352 { 1353 this.value = new Array(); 1354 this.is_indefinite_form = false; 1355 } 1356 }; 1357 //************************************************************************************** 1358 local.ASN1_CONSTRUCTED_value_block.prototype = new local.value_block(); 1359 local.ASN1_CONSTRUCTED_value_block.constructor = local.ASN1_CONSTRUCTED_value_block; 1360 //************************************************************************************** 1361 local.ASN1_CONSTRUCTED_value_block.prototype.fromBER = 1362 function(input_buffer, input_offset, input_length) 1363 { 1364 /// <summary>Base function for converting block from BER encoded array of bytes</summary> 1365 /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param> 1366 /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param> 1367 /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param> 1368 1369 // #region Store initial offset and length 1370 var initial_offset = input_offset; 1371 var initial_length = input_length; 1372 // #endregion 1373 1374 // #region Basic check for parameters 1375 if(check_buffer_params.call(this, input_buffer, input_offset, input_length) === false) 1376 return (-1); 1377 // #endregion 1378 1379 // #region Getting Uint8Array from ArrayBuffer 1380 var int_buffer = new Uint8Array(input_buffer, input_offset, input_length); 1381 // #endregion 1382 1383 // #region Initial checks 1384 if(int_buffer.length == 0) 1385 { 1386 this.warnings.push("Zero buffer length"); 1387 return input_offset; 1388 } 1389 // #endregion 1390 1391 // #region Aux function 1392 function check_len(_indefinite_length, _length) 1393 { 1394 if(_indefinite_length == true) 1395 return 1; 1396 1397 return _length; 1398 } 1399 // #endregion 1400 1401 var current_offset = input_offset; 1402 1403 while(check_len(this.is_indefinite_form, input_length) > 0) 1404 { 1405 var return_object = fromBER_raw(input_buffer, current_offset, input_length); 1406 if(return_object.offset == (-1)) 1407 { 1408 this.error = return_object.result.error; 1409 this.warnings.concat(return_object.result.warnings); 1410 return (-1); 1411 } 1412 1413 current_offset = return_object.offset; 1414 1415 this.block_length += return_object.result.block_length; 1416 input_length -= return_object.result.block_length; 1417 1418 this.value.push(return_object.result); 1419 1420 if((this.is_indefinite_form == true) && (return_object.result.block_name() == in_window.org.pkijs.asn1.EOC.prototype.block_name())) 1421 break; 1422 } 1423 1424 if(this.is_indefinite_form == true) 1425 { 1426 if(this.value[this.value.length - 1].block_name() == in_window.org.pkijs.asn1.EOC.prototype.block_name()) 1427 this.value.pop(); 1428 else 1429 this.warnings.push("No EOC block encoded"); 1430 } 1431 1432 // #region Copy "input_buffer" to "value_before_decode" 1433 this.value_before_decode = util_copybuf_offset(input_buffer, initial_offset, initial_length); 1434 // #endregion 1435 1436 return current_offset; 1437 }; 1438 //************************************************************************************** 1439 local.ASN1_CONSTRUCTED_value_block.prototype.toBER = 1440 function(size_only) 1441 { 1442 /// <summary>Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)</summary> 1443 /// <param name="size_only" type="Boolean">Flag that we need only a size of encoding, not a real array of bytes</param> 1444 1445 if(typeof size_only === "undefined") 1446 size_only = false; 1447 1448 var ret_buf = new ArrayBuffer(0); 1449 1450 for(var i = 0; i < this.value.length; i++) 1451 { 1452 var value_buf = this.value[i].toBER(size_only); 1453 ret_buf = util_concatbuf(ret_buf, value_buf); 1454 } 1455 1456 return ret_buf; 1457 }; 1458 //************************************************************************************** 1459 local.ASN1_CONSTRUCTED_value_block.prototype.block_name = 1460 function() 1461 { 1462 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 1463 1464 return "ASN1_CONSTRUCTED_value_block"; 1465 }; 1466 //************************************************************************************** 1467 local.ASN1_CONSTRUCTED_value_block.prototype.toJSON = 1468 function() 1469 { 1470 /// <summary>Convertion for the block to JSON object</summary> 1471 1472 var _object = local.value_block.prototype.toJSON.call(this); 1473 1474 _object.block_name = local.ASN1_CONSTRUCTED_value_block.prototype.block_name.call(this); 1475 _object.is_indefinite_form = this.is_indefinite_form; 1476 _object.value = new Array(); 1477 for(var i = 0; i < this.value.length; i++) 1478 _object.value.push(this.value[i].toJSON()); 1479 1480 return _object; 1481 }; 1482 //************************************************************************************** 1483 in_window.org.pkijs.asn1.ASN1_CONSTRUCTED = 1484 function() 1485 { 1486 /// <summary>Base class of ASN.1 block for constructive values (constructive encoding)</summary> 1487 1488 in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]); 1489 1490 this.id_block.is_constructed = true; 1491 this.value_block = new local.ASN1_CONSTRUCTED_value_block(arguments[0]); 1492 }; 1493 //************************************************************************************** 1494 in_window.org.pkijs.asn1.ASN1_CONSTRUCTED.prototype = new in_window.org.pkijs.asn1.ASN1_block(); 1495 in_window.org.pkijs.asn1.ASN1_CONSTRUCTED.constructor = in_window.org.pkijs.asn1.ASN1_CONSTRUCTED; 1496 //************************************************************************************** 1497 in_window.org.pkijs.asn1.ASN1_CONSTRUCTED.prototype.block_name = 1498 function() 1499 { 1500 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 1501 1502 return "CONSTRUCTED"; 1503 }; 1504 //************************************************************************************** 1505 in_window.org.pkijs.asn1.ASN1_CONSTRUCTED.prototype.fromBER = 1506 function(input_buffer, input_offset, input_length) 1507 { 1508 /// <summary>Base function for converting block from BER encoded array of bytes</summary> 1509 /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param> 1510 /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param> 1511 /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param> 1512 1513 this.value_block.is_indefinite_form = this.len_block.is_indefinite_form; 1514 1515 var result_offset = this.value_block.fromBER(input_buffer, input_offset, (this.len_block.is_indefinite_form == true) ? input_length : this.len_block.length); 1516 if(result_offset == (-1)) 1517 { 1518 this.error = this.value_block.error; 1519 return result_offset; 1520 } 1521 1522 if(this.id_block.error.length == 0) 1523 this.block_length += this.id_block.block_length; 1524 1525 if(this.len_block.error.length == 0) 1526 this.block_length += this.len_block.block_length; 1527 1528 if(this.value_block.error.length == 0) 1529 this.block_length += this.value_block.block_length; 1530 1531 return result_offset; 1532 }; 1533 //************************************************************************************** 1534 in_window.org.pkijs.asn1.ASN1_CONSTRUCTED.prototype.toJSON = 1535 function() 1536 { 1537 /// <summary>Convertion for the block to JSON object</summary> 1538 1539 var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this); 1540 1541 _object.block_name = in_window.org.pkijs.asn1.ASN1_CONSTRUCTED.prototype.block_name.call(this); 1542 1543 return _object; 1544 }; 1545 //************************************************************************************** 1546 // #endregion 1547 //************************************************************************************** 1548 // #region Declaration of ASN.1 EOC type class 1549 //************************************************************************************** 1550 local.EOC_value_block = 1551 function() 1552 { 1553 local.value_block.call(this, arguments[0]); 1554 }; 1555 //************************************************************************************** 1556 local.EOC_value_block.prototype = new local.value_block(); 1557 local.EOC_value_block.constructor = local.EOC_value_block; 1558 //************************************************************************************** 1559 local.EOC_value_block.prototype.fromBER = 1560 function(input_buffer, input_offset, input_length) 1561 { 1562 /// <summary>Base function for converting block from BER encoded array of bytes</summary> 1563 /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param> 1564 /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param> 1565 /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param> 1566 1567 // #region There is no "value block" for EOC type and we need to return the same offset 1568 return input_offset; 1569 // #endregion 1570 }; 1571 //************************************************************************************** 1572 local.EOC_value_block.prototype.toBER = 1573 function(size_only) 1574 { 1575 /// <summary>Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)</summary> 1576 /// <param name="size_only" type="Boolean">Flag that we need only a size of encoding, not a real array of bytes</param> 1577 1578 return (new ArrayBuffer(0)); 1579 }; 1580 //************************************************************************************** 1581 local.EOC_value_block.prototype.block_name = 1582 function() 1583 { 1584 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 1585 1586 return "EOC_value_block"; 1587 }; 1588 //************************************************************************************** 1589 local.EOC_value_block.prototype.toJSON = 1590 function() 1591 { 1592 /// <summary>Convertion for the block to JSON object</summary> 1593 1594 var _object = local.value_block.prototype.toJSON.call(this); 1595 1596 _object.block_name = local.EOC_value_block.prototype.block_name.call(this); 1597 1598 return _object; 1599 }; 1600 //************************************************************************************** 1601 in_window.org.pkijs.asn1.EOC = 1602 function() 1603 { 1604 in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]); 1605 1606 this.value_block = new local.EOC_value_block(); 1607 1608 this.id_block.tag_class = 1; // UNIVERSAL 1609 this.id_block.tag_number = 0; // EOC 1610 }; 1611 //************************************************************************************** 1612 in_window.org.pkijs.asn1.EOC.prototype = new in_window.org.pkijs.asn1.ASN1_block(); 1613 in_window.org.pkijs.asn1.EOC.constructor = local.EOC_value_block; 1614 //************************************************************************************** 1615 in_window.org.pkijs.asn1.EOC.prototype.block_name = 1616 function() 1617 { 1618 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 1619 1620 return "END_OF_CONTENT"; 1621 }; 1622 //************************************************************************************** 1623 in_window.org.pkijs.asn1.EOC.prototype.toJSON = 1624 function() 1625 { 1626 /// <summary>Convertion for the block to JSON object</summary> 1627 1628 var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this); 1629 1630 _object.block_name = in_window.org.pkijs.asn1.EOC.prototype.block_name.call(this); 1631 1632 return _object; 1633 }; 1634 //************************************************************************************** 1635 // #endregion 1636 //************************************************************************************** 1637 // #region Declaration of ASN.1 BOOLEAN type class 1638 //************************************************************************************** 1639 local.BOOLEAN_value_block = 1640 function() 1641 { 1642 local.value_block.call(this, arguments[0]); 1643 1644 if(arguments[0] instanceof Object) 1645 { 1646 this.value = in_window.org.pkijs.getValue(arguments[0], "value", false); 1647 1648 // #region Variables from hex_block class 1649 this.is_hex_only = in_window.org.pkijs.getValue(arguments[0], "is_hex_only", false); 1650 if("value_hex" in arguments[0]) 1651 this.value_hex = util_copybuf(arguments[0].value_hex); 1652 else 1653 { 1654 this.value_hex = new ArrayBuffer(1); 1655 if(this.value === true) 1656 { 1657 var view = new Uint8Array(this.value_hex); 1658 view[0] = 0xFF; 1659 } 1660 } 1661 // #endregion 1662 } 1663 else 1664 { 1665 this.value = false; 1666 1667 // #region Variables from hex_block class 1668 this.is_hex_only = false; 1669 this.value_hex = new ArrayBuffer(1); 1670 // #endregion 1671 } 1672 }; 1673 //************************************************************************************** 1674 local.BOOLEAN_value_block.prototype = new local.value_block(); 1675 local.BOOLEAN_value_block.constructor = local.BOOLEAN_value_block; 1676 //************************************************************************************** 1677 local.BOOLEAN_value_block.prototype.fromBER = 1678 function(input_buffer, input_offset, input_length) 1679 { 1680 /// <summary>Base function for converting block from BER encoded array of bytes</summary> 1681 /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param> 1682 /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param> 1683 /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param> 1684 1685 // #region Basic check for parameters 1686 if(check_buffer_params.call(this, input_buffer, input_offset, input_length) === false) 1687 return (-1); 1688 // #endregion 1689 1690 // #region Getting Uint8Array from ArrayBuffer 1691 var int_buffer = new Uint8Array(input_buffer, input_offset, input_length); 1692 // #endregion 1693 1694 if(input_length > 1) 1695 this.warnings.push("BOOLEAN value encoded in more then 1 octet"); 1696 1697 this.value = int_buffer[0] != 0x00; 1698 1699 this.is_hex_only = true; 1700 1701 // #region Copy input buffer to internal array 1702 this.value_hex = new ArrayBuffer(int_buffer.length); 1703 var view = new Uint8Array(this.value_hex); 1704 1705 for(var i = 0; i < int_buffer.length; i++) 1706 view[i] = int_buffer[i]; 1707 // #endregion 1708 1709 this.block_length = input_length; 1710 1711 return (input_offset + input_length); 1712 }; 1713 //************************************************************************************** 1714 local.BOOLEAN_value_block.prototype.toBER = 1715 function(size_only) 1716 { 1717 /// <summary>Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)</summary> 1718 /// <param name="size_only" type="Boolean">Flag that we need only a size of encoding, not a real array of bytes</param> 1719 1720 if(typeof size_only === "undefined") 1721 size_only = false; 1722 1723 return this.value_hex; 1724 }; 1725 //************************************************************************************** 1726 local.BOOLEAN_value_block.prototype.block_name = 1727 function() 1728 { 1729 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 1730 1731 return "BOOLEAN_value_block"; 1732 }; 1733 //************************************************************************************** 1734 local.BOOLEAN_value_block.prototype.toJSON = 1735 function() 1736 { 1737 /// <summary>Convertion for the block to JSON object</summary> 1738 1739 var _object = local.value_block.prototype.toJSON.call(this); 1740 1741 _object.block_name = local.BOOLEAN_value_block.prototype.block_name.call(this); 1742 _object.value = this.value; 1743 _object.is_hex_only = this.is_hex_only; 1744 _object.value_hex = in_window.org.pkijs.bufferToHexCodes(this.value_hex, 0, this.value_hex.byteLength); 1745 1746 return _object; 1747 }; 1748 //************************************************************************************** 1749 in_window.org.pkijs.asn1.BOOLEAN = 1750 function() 1751 { 1752 in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]); 1753 1754 this.value_block = new local.BOOLEAN_value_block(arguments[0]); 1755 1756 this.id_block.tag_class = 1; // UNIVERSAL 1757 this.id_block.tag_number = 1; // BOOLEAN 1758 }; 1759 //************************************************************************************** 1760 in_window.org.pkijs.asn1.BOOLEAN.prototype = new in_window.org.pkijs.asn1.ASN1_block(); 1761 in_window.org.pkijs.asn1.BOOLEAN.constructor = local.BOOLEAN_value_block; 1762 //************************************************************************************** 1763 in_window.org.pkijs.asn1.BOOLEAN.prototype.block_name = 1764 function() 1765 { 1766 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 1767 1768 return "BOOLEAN"; 1769 }; 1770 //************************************************************************************** 1771 in_window.org.pkijs.asn1.BOOLEAN.prototype.toJSON = 1772 function() 1773 { 1774 /// <summary>Convertion for the block to JSON object</summary> 1775 1776 var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this); 1777 1778 _object.block_name = in_window.org.pkijs.asn1.BOOLEAN.prototype.block_name.call(this); 1779 1780 return _object; 1781 }; 1782 //************************************************************************************** 1783 // #endregion 1784 //************************************************************************************** 1785 // #region Declaration of ASN.1 SEQUENCE and SET type classes 1786 //************************************************************************************** 1787 in_window.org.pkijs.asn1.SEQUENCE = 1788 function() 1789 { 1790 in_window.org.pkijs.asn1.ASN1_CONSTRUCTED.call(this, arguments[0]); 1791 1792 this.id_block.tag_class = 1; // UNIVERSAL 1793 this.id_block.tag_number = 16; // SEQUENCE 1794 }; 1795 //************************************************************************************** 1796 in_window.org.pkijs.asn1.SEQUENCE.prototype = new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED(); 1797 in_window.org.pkijs.asn1.SEQUENCE.constructor = in_window.org.pkijs.asn1.SEQUENCE; 1798 //************************************************************************************** 1799 in_window.org.pkijs.asn1.SEQUENCE.prototype.block_name = 1800 function() 1801 { 1802 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 1803 1804 return "SEQUENCE"; 1805 }; 1806 //************************************************************************************** 1807 in_window.org.pkijs.asn1.SEQUENCE.prototype.toJSON = 1808 function() 1809 { 1810 /// <summary>Convertion for the block to JSON object</summary> 1811 1812 var _object = in_window.org.pkijs.asn1.ASN1_CONSTRUCTED.prototype.toJSON.call(this); 1813 1814 _object.block_name = in_window.org.pkijs.asn1.SEQUENCE.prototype.block_name.call(this); 1815 1816 return _object; 1817 }; 1818 //************************************************************************************** 1819 in_window.org.pkijs.asn1.SET = 1820 function() 1821 { 1822 in_window.org.pkijs.asn1.ASN1_CONSTRUCTED.call(this, arguments[0]); 1823 1824 this.id_block.tag_class = 1; // UNIVERSAL 1825 this.id_block.tag_number = 17; // SET 1826 }; 1827 //************************************************************************************** 1828 in_window.org.pkijs.asn1.SET.prototype = new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED(); 1829 in_window.org.pkijs.asn1.SET.constructor = in_window.org.pkijs.asn1.SET; 1830 //************************************************************************************** 1831 in_window.org.pkijs.asn1.SET.prototype.block_name = 1832 function() 1833 { 1834 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 1835 1836 return "SET"; 1837 }; 1838 //************************************************************************************** 1839 in_window.org.pkijs.asn1.SET.prototype.toJSON = 1840 function() 1841 { 1842 /// <summary>Convertion for the block to JSON object</summary> 1843 1844 var _object = in_window.org.pkijs.asn1.ASN1_CONSTRUCTED.prototype.toJSON.call(this); 1845 1846 _object.block_name = in_window.org.pkijs.asn1.SET.prototype.block_name.call(this); 1847 1848 return _object; 1849 }; 1850 //************************************************************************************** 1851 // #endregion 1852 //************************************************************************************** 1853 // #region Declaration of ASN.1 NULL type class 1854 //************************************************************************************** 1855 in_window.org.pkijs.asn1.NULL = 1856 function() 1857 { 1858 in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]); 1859 1860 this.id_block.tag_class = 1; // UNIVERSAL 1861 this.id_block.tag_number = 5; // NULL 1862 }; 1863 //************************************************************************************** 1864 in_window.org.pkijs.asn1.NULL.prototype = new in_window.org.pkijs.asn1.ASN1_block(); 1865 in_window.org.pkijs.asn1.NULL.constructor = in_window.org.pkijs.asn1.NULL; 1866 //************************************************************************************** 1867 in_window.org.pkijs.asn1.NULL.prototype.block_name = 1868 function() 1869 { 1870 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 1871 1872 return "NULL"; 1873 }; 1874 //************************************************************************************** 1875 in_window.org.pkijs.asn1.NULL.prototype.fromBER = 1876 function(input_buffer, input_offset, input_length) 1877 { 1878 /// <summary>Base function for converting block from BER encoded array of bytes</summary> 1879 /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param> 1880 /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param> 1881 /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param> 1882 1883 if(this.len_block.length > 0) 1884 this.warnings.push("Non-zero length of value block for NULL type"); 1885 1886 if(this.id_block.error.length === 0) 1887 this.block_length += this.id_block.block_length; 1888 1889 if(this.len_block.error.length === 0) 1890 this.block_length += this.len_block.block_length; 1891 1892 this.block_length += input_length; 1893 1894 return (input_offset + input_length); 1895 }; 1896 //************************************************************************************** 1897 in_window.org.pkijs.asn1.NULL.prototype.toBER = 1898 function(size_only) 1899 { 1900 /// <summary>Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)</summary> 1901 /// <param name="size_only" type="Boolean">Flag that we need only a size of encoding, not a real array of bytes</param> 1902 1903 if(typeof size_only === "undefined") 1904 size_only = false; 1905 1906 var ret_buf = new ArrayBuffer(2); 1907 1908 if(size_only === true) 1909 return ret_buf; 1910 1911 var ret_view = new Uint8Array(ret_buf); 1912 ret_view[0] = 0x05; 1913 ret_view[1] = 0x00; 1914 1915 return ret_buf; 1916 }; 1917 //************************************************************************************** 1918 in_window.org.pkijs.asn1.NULL.prototype.toJSON = 1919 function() 1920 { 1921 /// <summary>Convertion for the block to JSON object</summary> 1922 1923 var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this); 1924 1925 _object.block_name = in_window.org.pkijs.asn1.NULL.prototype.block_name.call(this); 1926 1927 return _object; 1928 }; 1929 //************************************************************************************** 1930 // #endregion 1931 //************************************************************************************** 1932 // #region Declaration of ASN.1 OCTETSTRING type class 1933 //************************************************************************************** 1934 local.OCTETSTRING_value_block = 1935 function() 1936 { 1937 /// <param name="input_value_hex" type="ArrayBuffer"></param> 1938 /// <param name="input_value" type="Array"></param> 1939 /// <param name="input_constructed" type="Boolean"></param> 1940 /// <remarks>Value for the OCTETSTRING may be as hex, as well as a constructed value.</remarks> 1941 /// <remarks>Constructed values consists of other OCTETSTRINGs</remarks> 1942 1943 local.ASN1_CONSTRUCTED_value_block.call(this, arguments[0]); 1944 1945 if(arguments[0] instanceof Object) 1946 { 1947 this.is_constructed = in_window.org.pkijs.getValue(arguments[0], "is_constructed", false); 1948 1949 // #region Variables from hex_block type 1950 this.is_hex_only = in_window.org.pkijs.getValue(arguments[0], "is_hex_only", false); 1951 if("value_hex" in arguments[0]) 1952 this.value_hex = util_copybuf(arguments[0].value_hex); 1953 else 1954 this.value_hex = new ArrayBuffer(0); 1955 // #endregion 1956 } 1957 else 1958 { 1959 this.is_constructed = false; 1960 1961 // #region Variables from hex_block type 1962 this.is_hex_only = false; 1963 this.value_hex = new ArrayBuffer(0); 1964 // #endregion 1965 } 1966 }; 1967 //************************************************************************************** 1968 local.OCTETSTRING_value_block.prototype = new local.ASN1_CONSTRUCTED_value_block(); 1969 local.OCTETSTRING_value_block.constructor = local.OCTETSTRING_value_block; 1970 //************************************************************************************** 1971 local.OCTETSTRING_value_block.prototype.fromBER = 1972 function(input_buffer, input_offset, input_length) 1973 { 1974 /// <summary>Base function for converting block from BER encoded array of bytes</summary> 1975 /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param> 1976 /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param> 1977 /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param> 1978 1979 var result_offset = 0; 1980 1981 if(this.is_constructed == true) 1982 { 1983 this.is_hex_only = false; 1984 1985 result_offset = local.ASN1_CONSTRUCTED_value_block.prototype.fromBER.call(this, input_buffer, input_offset, input_length); 1986 if(result_offset == (-1)) 1987 return result_offset; 1988 1989 for(var i = 0; i < this.value.length; i++) 1990 { 1991 var current_block_name = this.value[i].block_name(); 1992 1993 if(current_block_name == in_window.org.pkijs.asn1.EOC.prototype.block_name()) 1994 { 1995 if(this.is_indefinite_form == true) 1996 break; 1997 else 1998 { 1999 this.error = "EOC is unexpected, OCTET STRING may consists of OCTET STRINGs only"; 2000 return (-1); 2001 } 2002 } 2003 2004 if(current_block_name != in_window.org.pkijs.asn1.OCTETSTRING.prototype.block_name()) 2005 { 2006 this.error = "OCTET STRING may consists of OCTET STRINGs only"; 2007 return (-1); 2008 } 2009 } 2010 } 2011 else 2012 { 2013 this.is_hex_only = true; 2014 2015 result_offset = local.hex_block.prototype.fromBER.call(this, input_buffer, input_offset, input_length); 2016 this.block_length = input_length; 2017 } 2018 2019 return result_offset; 2020 }; 2021 //************************************************************************************** 2022 local.OCTETSTRING_value_block.prototype.toBER = 2023 function(size_only) 2024 { 2025 /// <summary>Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)</summary> 2026 /// <param name="size_only" type="Boolean">Flag that we need only a size of encoding, not a real array of bytes</param> 2027 2028 if(typeof size_only === "undefined") 2029 size_only = false; 2030 2031 if(this.is_constructed === true) 2032 return local.ASN1_CONSTRUCTED_value_block.prototype.toBER.call(this, size_only); 2033 else 2034 { 2035 var ret_buf = new ArrayBuffer(this.value_hex.byteLength); 2036 2037 if(size_only === true) 2038 return ret_buf; 2039 2040 if(this.value_hex.byteLength == 0) 2041 return ret_buf; 2042 2043 ret_buf = util_copybuf(this.value_hex); 2044 2045 return ret_buf; 2046 } 2047 2048 return (new ArrayBuffer(0)); 2049 }; 2050 //************************************************************************************** 2051 local.OCTETSTRING_value_block.prototype.block_name = 2052 function() 2053 { 2054 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 2055 2056 return "OCTETSTRING_value_block"; 2057 }; 2058 //************************************************************************************** 2059 local.OCTETSTRING_value_block.prototype.toJSON = 2060 function() 2061 { 2062 /// <summary>Convertion for the block to JSON object</summary> 2063 2064 var _object = local.ASN1_CONSTRUCTED_value_block.prototype.toJSON.call(this); 2065 2066 _object.block_name = local.OCTETSTRING_value_block.prototype.block_name.call(this); 2067 _object.is_constructed = this.is_constructed; 2068 _object.is_hex_only = this.is_hex_only; 2069 _object.value_hex = in_window.org.pkijs.bufferToHexCodes(this.value_hex, 0, this.value_hex.byteLength); 2070 2071 return _object; 2072 }; 2073 //************************************************************************************** 2074 in_window.org.pkijs.asn1.OCTETSTRING = 2075 function() 2076 { 2077 in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]); 2078 2079 this.value_block = new local.OCTETSTRING_value_block(arguments[0]); 2080 2081 this.id_block.tag_class = 1; // UNIVERSAL 2082 this.id_block.tag_number = 4; // OCTETSTRING 2083 }; 2084 //************************************************************************************** 2085 in_window.org.pkijs.asn1.OCTETSTRING.prototype = new in_window.org.pkijs.asn1.ASN1_block(); 2086 in_window.org.pkijs.asn1.OCTETSTRING.constructor = in_window.org.pkijs.asn1.OCTETSTRING; 2087 //************************************************************************************** 2088 in_window.org.pkijs.asn1.OCTETSTRING.prototype.fromBER = 2089 function(input_buffer, input_offset, input_length) 2090 { 2091 /// <summary>Base function for converting block from BER encoded array of bytes</summary> 2092 /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param> 2093 /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param> 2094 /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param> 2095 2096 this.value_block.is_constructed = this.id_block.is_constructed; 2097 this.value_block.is_indefinite_form = this.len_block.is_indefinite_form; 2098 2099 // #region Ability to encode empty OCTET STRING 2100 if(input_length == 0) 2101 { 2102 if(this.id_block.error.length == 0) 2103 this.block_length += this.id_block.block_length; 2104 2105 if(this.len_block.error.length == 0) 2106 this.block_length += this.len_block.block_length; 2107 2108 return input_offset; 2109 } 2110 // #endregion 2111 2112 return in_window.org.pkijs.asn1.ASN1_block.prototype.fromBER.call(this, input_buffer, input_offset, input_length); 2113 }; 2114 //************************************************************************************** 2115 in_window.org.pkijs.asn1.OCTETSTRING.prototype.block_name = 2116 function() 2117 { 2118 return "OCTETSTRING"; 2119 }; 2120 //************************************************************************************** 2121 in_window.org.pkijs.asn1.OCTETSTRING.prototype.toJSON = 2122 function() 2123 { 2124 /// <summary>Convertion for the block to JSON object</summary> 2125 2126 var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this); 2127 2128 _object.block_name = in_window.org.pkijs.asn1.OCTETSTRING.prototype.block_name.call(this); 2129 2130 return _object; 2131 }; 2132 //************************************************************************************** 2133 in_window.org.pkijs.asn1.OCTETSTRING.prototype.isEqual = 2134 function(octetString) 2135 { 2136 /// <summaryChecking that two OCTETSTRINGs are equal></summary> 2137 /// <param name="octetString" type="in_window.org.pkijs.asn1.OCTETSTRING">The OCTETSTRING to compare with</param> 2138 2139 // #region Check input type 2140 if((octetString instanceof in_window.org.pkijs.asn1.OCTETSTRING) == false) 2141 return false; 2142 // #endregion 2143 2144 // #region Compare two JSON strings 2145 if(JSON.stringify(this) != JSON.stringify(octetString)) 2146 return false; 2147 // #endregion 2148 2149 return true; 2150 }; 2151 //************************************************************************************** 2152 // #endregion 2153 //************************************************************************************** 2154 // #region Declaration of ASN.1 BITSTRING type class 2155 //************************************************************************************** 2156 local.BITSTRING_value_block = 2157 function() 2158 { 2159 local.ASN1_CONSTRUCTED_value_block.call(this, arguments[0]); 2160 2161 if(arguments[0] instanceof Object) 2162 { 2163 this.unused_bits = in_window.org.pkijs.getValue(arguments[0], "unused_bits", 0); 2164 this.is_constructed = in_window.org.pkijs.getValue(arguments[0], "is_constructed", false); 2165 2166 // #region Variables from hex_block type 2167 this.is_hex_only = in_window.org.pkijs.getValue(arguments[0], "is_hex_only", false); 2168 2169 if("value_hex" in arguments[0]) 2170 this.value_hex = util_copybuf(arguments[0].value_hex); 2171 else 2172 this.value_hex = new ArrayBuffer(0); 2173 2174 this.block_length = this.value_hex.byteLength; 2175 // #endregion 2176 } 2177 else 2178 { 2179 this.unused_bits = 0; 2180 this.is_constructed = false; 2181 2182 // #region Variables from hex_block type 2183 this.is_hex_only = false; 2184 this.value_hex = new ArrayBuffer(0); 2185 // #endregion 2186 } 2187 }; 2188 //************************************************************************************** 2189 local.BITSTRING_value_block.prototype = new local.ASN1_CONSTRUCTED_value_block(); 2190 local.BITSTRING_value_block.constructor = local.BITSTRING_value_block; 2191 //************************************************************************************** 2192 local.BITSTRING_value_block.prototype.fromBER = 2193 function(input_buffer, input_offset, input_length) 2194 { 2195 /// <summary>Base function for converting block from BER encoded array of bytes</summary> 2196 /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param> 2197 /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param> 2198 /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param> 2199 2200 // #region Ability to decode zero-length BITSTRING value 2201 if(input_length == 0) 2202 return input_offset; 2203 // #endregion 2204 2205 var result_offset = (-1); 2206 2207 // #region If the BISTRING supposed to be a constructed value 2208 if(this.is_constructed == true) 2209 { 2210 result_offset = local.ASN1_CONSTRUCTED_value_block.prototype.fromBER.call(this, input_buffer, input_offset, input_length); 2211 if(result_offset == (-1)) 2212 return result_offset; 2213 2214 for(var i = 0; i < this.value.length; i++) 2215 { 2216 var current_block_name = this.value[i].block_name(); 2217 2218 if(current_block_name == in_window.org.pkijs.asn1.EOC.prototype.block_name()) 2219 { 2220 if(this.is_indefinite_form == true) 2221 break; 2222 else 2223 { 2224 this.error = "EOC is unexpected, BIT STRING may consists of BIT STRINGs only"; 2225 return (-1); 2226 } 2227 } 2228 2229 if(current_block_name != in_window.org.pkijs.asn1.BITSTRING.prototype.block_name()) 2230 { 2231 this.error = "BIT STRING may consists of BIT STRINGs only"; 2232 return (-1); 2233 } 2234 2235 if((this.unused_bits > 0) && (this.value[i].unused_bits > 0)) 2236 { 2237 this.error = "Usign of \"unused bits\" inside constructive BIT STRING allowed for least one only"; 2238 return (-1); 2239 } 2240 else 2241 { 2242 this.unused_bits = this.value[i].unused_bits; 2243 if(this.unused_bits > 7) 2244 { 2245 this.error = "Unused bits for BITSTRING must be in range 0-7"; 2246 return (-1); 2247 } 2248 } 2249 } 2250 2251 return result_offset; 2252 } 2253 // #endregion 2254 // #region If the BITSTRING supposed to be a primitive value 2255 else 2256 { 2257 // #region Basic check for parameters 2258 if(check_buffer_params.call(this, input_buffer, input_offset, input_length) === false) 2259 return (-1); 2260 // #endregion 2261 2262 var int_buffer = new Uint8Array(input_buffer, input_offset, input_length); 2263 2264 this.unused_bits = int_buffer[0]; 2265 if(this.unused_bits > 7) 2266 { 2267 this.error = "Unused bits for BITSTRING must be in range 0-7"; 2268 return (-1); 2269 } 2270 2271 // #region Copy input buffer to internal buffer 2272 this.value_hex = new ArrayBuffer(int_buffer.length - 1); 2273 var view = new Uint8Array(this.value_hex); 2274 for(var i = 0; i < (input_length - 1) ; i++) 2275 view[i] = int_buffer[i + 1]; 2276 // #endregion 2277 2278 this.block_length = int_buffer.length; 2279 2280 return (input_offset + input_length); 2281 } 2282 // #endregion 2283 }; 2284 //************************************************************************************** 2285 local.BITSTRING_value_block.prototype.toBER = 2286 function(size_only) 2287 { 2288 /// <summary>Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)</summary> 2289 /// <param name="size_only" type="Boolean">Flag that we need only a size of encoding, not a real array of bytes</param> 2290 2291 if(typeof size_only === "undefined") 2292 size_only = false; 2293 2294 if(this.is_constructed === true) 2295 return local.ASN1_CONSTRUCTED_value_block.prototype.toBER.call(this, size_only); 2296 else 2297 { 2298 if(size_only === true) 2299 return (new ArrayBuffer(this.value_hex.byteLength + 1)); 2300 2301 if(this.value_hex.byteLength == 0) 2302 return (new ArrayBuffer(0)); 2303 2304 var cur_view = new Uint8Array(this.value_hex); 2305 2306 var ret_buf = new ArrayBuffer(this.value_hex.byteLength + 1); 2307 var ret_view = new Uint8Array(ret_buf); 2308 2309 ret_view[0] = this.unused_bits; 2310 2311 for(var i = 0; i < this.value_hex.byteLength; i++) 2312 ret_view[i + 1] = cur_view[i]; 2313 2314 return ret_buf; 2315 } 2316 2317 return (new ArrayBuffer(0)); 2318 }; 2319 //************************************************************************************** 2320 local.BITSTRING_value_block.prototype.block_name = 2321 function() 2322 { 2323 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 2324 2325 return "BITSTRING_value_block"; 2326 }; 2327 //************************************************************************************** 2328 local.BITSTRING_value_block.prototype.toJSON = 2329 function() 2330 { 2331 /// <summary>Convertion for the block to JSON object</summary> 2332 2333 var _object = local.ASN1_CONSTRUCTED_value_block.prototype.toJSON.call(this); 2334 2335 _object.block_name = local.BITSTRING_value_block.prototype.block_name.call(this); 2336 _object.unused_bits = this.unused_bits; 2337 _object.is_constructed = this.is_constructed; 2338 _object.is_hex_only = this.is_hex_only; 2339 _object.value_hex = in_window.org.pkijs.bufferToHexCodes(this.value_hex, 0, this.value_hex.byteLength); 2340 2341 return _object; 2342 }; 2343 //************************************************************************************** 2344 in_window.org.pkijs.asn1.BITSTRING = 2345 function() 2346 { 2347 in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]); 2348 2349 this.value_block = new local.BITSTRING_value_block(arguments[0]); 2350 2351 this.id_block.tag_class = 1; // UNIVERSAL 2352 this.id_block.tag_number = 3; // BITSTRING 2353 }; 2354 //************************************************************************************** 2355 in_window.org.pkijs.asn1.BITSTRING.prototype = new in_window.org.pkijs.asn1.ASN1_block(); 2356 in_window.org.pkijs.asn1.BITSTRING.constructor = in_window.org.pkijs.asn1.BITSTRING; 2357 //************************************************************************************** 2358 in_window.org.pkijs.asn1.BITSTRING.prototype.block_name = 2359 function() 2360 { 2361 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 2362 2363 return "BITSTRING"; 2364 }; 2365 //************************************************************************************** 2366 in_window.org.pkijs.asn1.BITSTRING.prototype.fromBER = 2367 function(input_buffer, input_offset, input_length) 2368 { 2369 /// <summary>Base function for converting block from BER encoded array of bytes</summary> 2370 /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param> 2371 /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param> 2372 /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param> 2373 2374 // #region Ability to encode empty BITSTRING 2375 if(input_length == 0) 2376 return input_offset; 2377 // #endregion 2378 2379 this.value_block.is_constructed = this.id_block.is_constructed; 2380 this.value_block.is_indefinite_form = this.len_block.is_indefinite_form; 2381 2382 return in_window.org.pkijs.asn1.ASN1_block.prototype.fromBER.call(this, input_buffer, input_offset, input_length); 2383 }; 2384 //************************************************************************************** 2385 in_window.org.pkijs.asn1.BITSTRING.prototype.toJSON = 2386 function() 2387 { 2388 /// <summary>Convertion for the block to JSON object</summary> 2389 2390 var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this); 2391 2392 _object.block_name = in_window.org.pkijs.asn1.BITSTRING.prototype.block_name.call(this); 2393 2394 return _object; 2395 }; 2396 //************************************************************************************** 2397 // #endregion 2398 //************************************************************************************** 2399 // #region Declaration of ASN.1 INTEGER type class 2400 //************************************************************************************** 2401 local.INTEGER_value_block = 2402 function() 2403 { 2404 local.value_block.call(this, arguments[0]); 2405 2406 if(arguments[0] instanceof Object) 2407 { 2408 this.value_dec = in_window.org.pkijs.getValue(arguments[0], "value", 0); 2409 2410 // #region Variables from hex_block type 2411 this.is_hex_only = in_window.org.pkijs.getValue(arguments[0], "is_hex_only", false); 2412 if("value_hex" in arguments[0]) 2413 { 2414 this.value_hex = util_copybuf(arguments[0].value_hex); 2415 2416 if(this.value_hex.byteLength >= 4) // Dummy's protection 2417 this.is_hex_only = true; 2418 else 2419 this.value_dec = util_decode_tc.call(this); 2420 } 2421 else 2422 this.value_hex = util_encode_tc(this.value_dec); 2423 // #endregion 2424 } 2425 else 2426 { 2427 this.value_dec = 0; 2428 2429 // #region Variables from hex_block type 2430 this.is_hex_only = false; 2431 this.value_hex = new ArrayBuffer(0); 2432 // #endregion 2433 } 2434 }; 2435 //************************************************************************************** 2436 local.INTEGER_value_block.prototype = new local.value_block(); 2437 local.INTEGER_value_block.constructor = local.INTEGER_value_block; 2438 //************************************************************************************** 2439 local.INTEGER_value_block.prototype.fromBER = 2440 function(input_buffer, input_offset, input_length) 2441 { 2442 /// <summary>Base function for converting block from BER encoded array of bytes</summary> 2443 /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param> 2444 /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param> 2445 /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param> 2446 2447 var result_offset = local.hex_block.prototype.fromBER.call(this, input_buffer, input_offset, input_length); 2448 if(result_offset == (-1)) 2449 return result_offset; 2450 2451 if(this.value_hex.byteLength > 4) // In JavaScript we can effectively work with 32-bit integers only 2452 { 2453 this.warnings.push("Too big INTEGER for decoding, hex only"); 2454 this.is_hex_only = true; 2455 } 2456 else 2457 this.value_dec = util_decode_tc.call(this); 2458 2459 this.block_length = input_length; 2460 2461 return (input_offset + input_length); 2462 }; 2463 //************************************************************************************** 2464 local.INTEGER_value_block.prototype.toBER = 2465 function(size_only) 2466 { 2467 /// <summary>Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)</summary> 2468 /// <param name="size_only" type="Boolean">Flag that we need only a size of encoding, not a real array of bytes</param> 2469 2470 if(typeof size_only === "undefined") 2471 size_only = false; 2472 2473 if(this.is_hex_only === false) 2474 { 2475 var encoded_buf = util_encode_tc(this.value_dec); 2476 if(encoded_buf.byteLength == 0) 2477 { 2478 this.error = "Error during encoding INTEGER value"; 2479 return (new ArrayBuffer(0)); 2480 } 2481 2482 return util_copybuf(encoded_buf); 2483 } 2484 else 2485 return util_copybuf(this.value_hex); 2486 2487 return (new ArrayBuffer(0)); 2488 }; 2489 //************************************************************************************** 2490 local.INTEGER_value_block.prototype.block_name = 2491 function() 2492 { 2493 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 2494 2495 return "INTEGER_value_block"; 2496 }; 2497 //************************************************************************************** 2498 local.INTEGER_value_block.prototype.toJSON = 2499 function() 2500 { 2501 /// <summary>Convertion for the block to JSON object</summary> 2502 2503 var _object = local.value_block.prototype.toJSON.call(this); 2504 2505 _object.block_name = local.INTEGER_value_block.prototype.block_name.call(this); 2506 _object.value_dec = this.value_dec; 2507 _object.is_hex_only = this.is_hex_only; 2508 _object.value_hex = in_window.org.pkijs.bufferToHexCodes(this.value_hex, 0, this.value_hex.byteLength); 2509 2510 return _object; 2511 }; 2512 //************************************************************************************** 2513 in_window.org.pkijs.asn1.INTEGER = 2514 function() 2515 { 2516 in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]); 2517 2518 this.value_block = new local.INTEGER_value_block(arguments[0]); 2519 2520 this.id_block.tag_class = 1; // UNIVERSAL 2521 this.id_block.tag_number = 2; // INTEGER 2522 }; 2523 //************************************************************************************** 2524 in_window.org.pkijs.asn1.INTEGER.prototype = new in_window.org.pkijs.asn1.ASN1_block(); 2525 in_window.org.pkijs.asn1.INTEGER.constructor = in_window.org.pkijs.asn1.INTEGER; 2526 //************************************************************************************** 2527 in_window.org.pkijs.asn1.INTEGER.prototype.block_name = 2528 function() 2529 { 2530 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 2531 2532 return "INTEGER"; 2533 }; 2534 //************************************************************************************** 2535 in_window.org.pkijs.asn1.INTEGER.prototype.isEqual = 2536 function() 2537 { 2538 /// <summary>Compare two INTEGER object, or INTEGER and ArrayBuffer objects</summary> 2539 /// <returns type="Boolean"></returns> 2540 2541 if(arguments[0] instanceof in_window.org.pkijs.asn1.INTEGER) 2542 { 2543 if(this.value_block.is_hex_only && arguments[0].value_block.is_hex_only) // Compare two ArrayBuffers 2544 return in_window.org.pkijs.isEqual_buffer(this.value_block.value_hex, arguments[0].value_block.value_hex); 2545 else 2546 { 2547 if(this.value_block.is_hex_only === arguments[0].value_block.is_hex_only) 2548 return (this.value_block.value_dec == arguments[0].value_block.value_dec); 2549 else 2550 return false; 2551 } 2552 } 2553 else 2554 { 2555 if(arguments[0] instanceof ArrayBuffer) 2556 return in_window.org.pkijs.isEqual_buffer(this.value_block.value_hex, arguments[0]); 2557 else 2558 return false; 2559 } 2560 2561 return false; 2562 }; 2563 //************************************************************************************** 2564 in_window.org.pkijs.asn1.INTEGER.prototype.toJSON = 2565 function() 2566 { 2567 /// <summary>Convertion for the block to JSON object</summary> 2568 2569 var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this); 2570 2571 _object.block_name = in_window.org.pkijs.asn1.INTEGER.prototype.block_name.call(this); 2572 2573 return _object; 2574 }; 2575 //************************************************************************************** 2576 // #endregion 2577 //************************************************************************************** 2578 // #region Declaration of ASN.1 ENUMERATED type class 2579 //************************************************************************************** 2580 in_window.org.pkijs.asn1.ENUMERATED = 2581 function() 2582 { 2583 in_window.org.pkijs.asn1.INTEGER.call(this, arguments[0]); 2584 2585 this.id_block.tag_class = 1; // UNIVERSAL 2586 this.id_block.tag_number = 10; // ENUMERATED 2587 }; 2588 //************************************************************************************** 2589 in_window.org.pkijs.asn1.ENUMERATED.prototype = new in_window.org.pkijs.asn1.INTEGER(); 2590 in_window.org.pkijs.asn1.ENUMERATED.constructor = in_window.org.pkijs.asn1.ENUMERATED; 2591 //************************************************************************************** 2592 in_window.org.pkijs.asn1.ENUMERATED.prototype.block_name = 2593 function() 2594 { 2595 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 2596 2597 return "ENUMERATED"; 2598 }; 2599 //************************************************************************************** 2600 in_window.org.pkijs.asn1.ENUMERATED.prototype.toJSON = 2601 function() 2602 { 2603 /// <summary>Convertion for the block to JSON object</summary> 2604 2605 var _object = in_window.org.pkijs.asn1.INTEGER.prototype.toJSON.call(this); 2606 2607 _object.block_name = in_window.org.pkijs.asn1.ENUMERATED.prototype.block_name.call(this); 2608 2609 return _object; 2610 }; 2611 //************************************************************************************** 2612 // #endregion 2613 //************************************************************************************** 2614 // #region Declaration of ASN.1 OBJECT IDENTIFIER type class 2615 //************************************************************************************** 2616 local.SID_value_block = 2617 function() 2618 { 2619 local.hex_block.call(this, arguments[0]); 2620 2621 if(arguments[0] instanceof Object) 2622 { 2623 this.value_dec = in_window.org.pkijs.getValue(arguments[0], "value_dec", -1); 2624 this.is_first_sid = in_window.org.pkijs.getValue(arguments[0], "is_first_sid", false); 2625 } 2626 else 2627 { 2628 this.value_dec = (-1); 2629 this.is_first_sid = false; 2630 } 2631 }; 2632 //************************************************************************************** 2633 local.SID_value_block.prototype = new local.hex_block(); 2634 local.SID_value_block.constructor = local.SID_value_block; 2635 //************************************************************************************** 2636 local.SID_value_block.prototype.block_name = 2637 function() 2638 { 2639 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 2640 2641 return "sid_block"; 2642 }; 2643 //************************************************************************************** 2644 local.SID_value_block.prototype.fromBER = 2645 function(input_buffer, input_offset, input_length) 2646 { 2647 /// <summary>Base function for converting block from BER encoded array of bytes</summary> 2648 /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param> 2649 /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param> 2650 /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param> 2651 2652 if(input_length == 0) 2653 return input_offset; 2654 2655 // #region Basic check for parameters 2656 if(check_buffer_params.call(this, input_buffer, input_offset, input_length) === false) 2657 return (-1); 2658 // #endregion 2659 2660 var int_buffer = new Uint8Array(input_buffer, input_offset, input_length); 2661 2662 this.value_hex = new ArrayBuffer(input_length); 2663 var view = new Uint8Array(this.value_hex); 2664 2665 for(var i = 0; i < input_length; i++) 2666 { 2667 view[i] = int_buffer[i] & 0x7F; 2668 2669 this.block_length++; 2670 2671 if((int_buffer[i] & 0x80) == 0x00) 2672 break; 2673 } 2674 2675 // #region Ajust size of value_hex buffer 2676 var temp_value_hex = new ArrayBuffer(this.block_length); 2677 var temp_view = new Uint8Array(temp_value_hex); 2678 2679 for(var i = 0; i < this.block_length; i++) 2680 temp_view[i] = view[i]; 2681 2682 this.value_hex = util_copybuf(temp_value_hex); 2683 view = new Uint8Array(this.value_hex); 2684 // #endregion 2685 2686 if((int_buffer[this.block_length - 1] & 0x80) != 0x00) 2687 { 2688 this.error = "End of input reached before message was fully decoded"; 2689 return (-1); 2690 } 2691 2692 if(view[0] == 0x00) 2693 this.warnings.push("Needlessly long format of SID encoding"); 2694 2695 if(this.block_length <= 8) 2696 this.value_dec = util_frombase(view, 7); 2697 else 2698 { 2699 this.is_hex_only = true; 2700 this.warnings.push("Too big SID for decoding, hex only"); 2701 } 2702 2703 return (input_offset + this.block_length); 2704 }; 2705 //************************************************************************************** 2706 local.SID_value_block.prototype.toBER = 2707 function(size_only) 2708 { 2709 /// <summary>Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)</summary> 2710 /// <param name="size_only" type="Boolean">Flag that we need only a size of encoding, not a real array of bytes</param> 2711 2712 if(typeof size_only === "undefined") 2713 size_only = false; 2714 2715 if(this.is_hex_only) 2716 { 2717 if(size_only === true) 2718 return (new ArrayBuffer(this.value_hex.byteLength)); 2719 2720 var cur_view = new Uint8Array(this.value_hex); 2721 2722 var ret_buf = new ArrayBuffer(this.block_length); 2723 var ret_view = new Uint8Array(ret_buf); 2724 2725 for(var i = 0; i < (this.block_length - 1) ; i++) 2726 ret_view[i] = cur_view[i] | 0x80; 2727 2728 ret_view[this.block_length - 1] = cur_view[this.block_length - 1]; 2729 2730 return ret_buf; 2731 } 2732 else 2733 { 2734 var encoded_buf = util_tobase(this.value_dec, 7); 2735 if(encoded_buf.byteLength === 0) 2736 { 2737 this.error = "Error during encoding SID value"; 2738 return (new ArrayBuffer(0)); 2739 } 2740 2741 var ret_buf = new ArrayBuffer(encoded_buf.byteLength); 2742 2743 if(size_only === false) 2744 { 2745 var encoded_view = new Uint8Array(encoded_buf); 2746 var ret_view = new Uint8Array(ret_buf); 2747 2748 for(var i = 0; i < (encoded_buf.byteLength - 1) ; i++) 2749 ret_view[i] = encoded_view[i] | 0x80; 2750 2751 ret_view[encoded_buf.byteLength - 1] = encoded_view[encoded_buf.byteLength - 1]; 2752 } 2753 2754 return ret_buf; 2755 } 2756 }; 2757 //************************************************************************************** 2758 local.SID_value_block.prototype.toString = 2759 function() 2760 { 2761 var result = ""; 2762 2763 if(this.is_hex_only === true) 2764 result = to_hex_codes(this.value_hex); 2765 else 2766 { 2767 if(this.is_first_sid) 2768 { 2769 var sid_value = this.value_dec; 2770 2771 if(this.value_dec <= 39) 2772 result = "0."; 2773 else 2774 { 2775 if(this.value_dec <= 79) 2776 { 2777 result = "1."; 2778 sid_value -= 40; 2779 } 2780 else 2781 { 2782 result = "2."; 2783 sid_value -= 80; 2784 } 2785 } 2786 2787 result = result + sid_value.toString(); 2788 } 2789 else 2790 result = this.value_dec.toString(); 2791 } 2792 2793 return result; 2794 }; 2795 //************************************************************************************** 2796 local.SID_value_block.prototype.toJSON = 2797 function() 2798 { 2799 /// <summary>Convertion for the block to JSON object</summary> 2800 2801 var _object = local.hex_block.prototype.toJSON.call(this); 2802 2803 _object.block_name = local.SID_value_block.prototype.block_name.call(this); 2804 _object.value_dec = this.value_dec; 2805 _object.is_first_sid = this.is_first_sid; 2806 2807 return _object; 2808 }; 2809 //************************************************************************************** 2810 local.OID_value_block = 2811 function() 2812 { 2813 local.value_block.call(this, arguments[0]); 2814 2815 this.value = new Array(); 2816 2817 if(arguments[0] instanceof Object) 2818 this.fromString(in_window.org.pkijs.getValue(arguments[0], "value", "")); 2819 }; 2820 //************************************************************************************** 2821 local.OID_value_block.prototype = new local.value_block(); 2822 local.OID_value_block.constructor = local.OID_value_block; 2823 //************************************************************************************** 2824 local.OID_value_block.prototype.fromBER = 2825 function(input_buffer, input_offset, input_length) 2826 { 2827 /// <summary>Base function for converting block from BER encoded array of bytes</summary> 2828 /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param> 2829 /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param> 2830 /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param> 2831 2832 var result_offset = input_offset; 2833 2834 while(input_length > 0) 2835 { 2836 var sid_block = new local.SID_value_block(); 2837 result_offset = sid_block.fromBER(input_buffer, result_offset, input_length); 2838 if(result_offset == (-1)) 2839 { 2840 this.block_length = 0; 2841 this.error = sid_block.error; 2842 return result_offset; 2843 } 2844 2845 if(this.value.length == 0) 2846 sid_block.is_first_sid = true; 2847 2848 this.block_length += sid_block.block_length; 2849 input_length -= sid_block.block_length; 2850 2851 this.value.push(sid_block); 2852 } 2853 2854 return result_offset; 2855 }; 2856 //************************************************************************************** 2857 local.OID_value_block.prototype.toBER = 2858 function(size_only) 2859 { 2860 /// <summary>Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)</summary> 2861 /// <param name="size_only" type="Boolean">Flag that we need only a size of encoding, not a real array of bytes</param> 2862 2863 if(typeof size_only === "undefined") 2864 size_only = false; 2865 2866 var ret_buf = new ArrayBuffer(0); 2867 2868 for(var i = 0; i < this.value.length; i++) 2869 { 2870 var value_buf = this.value[i].toBER(size_only); 2871 if(value_buf.byteLength === 0) 2872 { 2873 this.error = this.value[i].error; 2874 return (new ArrayBuffer(0)); 2875 } 2876 2877 ret_buf = util_concatbuf(ret_buf, value_buf); 2878 } 2879 2880 return ret_buf; 2881 }; 2882 //************************************************************************************** 2883 local.OID_value_block.prototype.fromString = 2884 function(str) 2885 { 2886 this.value = new Array(); // Clear existing SID values 2887 2888 var pos1 = 0; 2889 var pos2 = 0; 2890 2891 var sid = ""; 2892 2893 var flag = false; 2894 2895 do 2896 { 2897 pos2 = str.indexOf('.', pos1); 2898 if(pos2 === (-1)) 2899 sid = str.substr(pos1); 2900 else 2901 sid = str.substr(pos1, pos2 - pos1); 2902 2903 pos1 = pos2 + 1; 2904 2905 if(flag) 2906 { 2907 var sid_block = this.value[0]; 2908 2909 var plus = 0; 2910 2911 switch(sid_block.value_dec) 2912 { 2913 case 0: 2914 break; 2915 case 1: 2916 plus = 40; 2917 break; 2918 case 2: 2919 plus = 80; 2920 break; 2921 default: 2922 this.value = new Array(); // clear SID array 2923 return false; // ??? 2924 } 2925 2926 var parsedSID = parseInt(sid, 10); 2927 if(isNaN(parsedSID)) 2928 return true; 2929 2930 sid_block.value_dec = parsedSID + plus; 2931 2932 flag = false; 2933 } 2934 else 2935 { 2936 var sid_block = new local.SID_value_block(); 2937 sid_block.value_dec = parseInt(sid, 10); 2938 if(isNaN(sid_block.value_dec)) 2939 return true; 2940 2941 if(this.value.length === 0) 2942 { 2943 sid_block.is_first_sid = true; 2944 flag = true; 2945 } 2946 2947 this.value.push(sid_block); 2948 } 2949 2950 } while(pos2 !== (-1)); 2951 2952 return true; 2953 }; 2954 //************************************************************************************** 2955 local.OID_value_block.prototype.toString = 2956 function() 2957 { 2958 var result = ""; 2959 var is_hex_only = false; 2960 2961 for(var i = 0; i < this.value.length; i++) 2962 { 2963 is_hex_only = this.value[i].is_hex_only; 2964 2965 var sid_str = this.value[i].toString(); 2966 2967 if(i !== 0) 2968 result = result + "."; 2969 2970 if(is_hex_only) 2971 { 2972 sid_str = "{" + sid_str + "}"; 2973 2974 if(this.value[i].is_first_sid) 2975 result = "2.{" + sid_str + " - 80}"; 2976 else 2977 result = result + sid_str; 2978 } 2979 else 2980 result = result + sid_str; 2981 } 2982 2983 return result; 2984 }; 2985 //************************************************************************************** 2986 local.OID_value_block.prototype.block_name = 2987 function() 2988 { 2989 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 2990 2991 return "OID_value_block"; 2992 }; 2993 //************************************************************************************** 2994 local.OID_value_block.prototype.toJSON = 2995 function() 2996 { 2997 /// <summary>Convertion for the block to JSON object</summary> 2998 2999 var _object = local.value_block.prototype.toJSON.call(this); 3000 3001 _object.block_name = local.OID_value_block.prototype.block_name.call(this); 3002 _object.value = local.OID_value_block.prototype.toString.call(this); 3003 _object.sid_array = new Array(); 3004 for(var i = 0; i < this.value.length; i++) 3005 _object.sid_array.push(this.value[i].toJSON()); 3006 3007 return _object; 3008 }; 3009 //************************************************************************************** 3010 in_window.org.pkijs.asn1.OID = 3011 function() 3012 { 3013 in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]); 3014 3015 this.value_block = new local.OID_value_block(arguments[0]); 3016 3017 this.id_block.tag_class = 1; // UNIVERSAL 3018 this.id_block.tag_number = 6; // OBJECT IDENTIFIER 3019 }; 3020 //************************************************************************************** 3021 in_window.org.pkijs.asn1.OID.prototype = new in_window.org.pkijs.asn1.ASN1_block(); 3022 in_window.org.pkijs.asn1.OID.constructor = in_window.org.pkijs.asn1.OID; 3023 //************************************************************************************** 3024 in_window.org.pkijs.asn1.OID.prototype.block_name = 3025 function() 3026 { 3027 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 3028 3029 return "OID"; 3030 }; 3031 //************************************************************************************** 3032 in_window.org.pkijs.asn1.OID.prototype.toJSON = 3033 function() 3034 { 3035 /// <summary>Convertion for the block to JSON object</summary> 3036 3037 var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this); 3038 3039 _object.block_name = in_window.org.pkijs.asn1.OID.prototype.block_name.call(this); 3040 3041 return _object; 3042 }; 3043 //************************************************************************************** 3044 // #endregion 3045 //************************************************************************************** 3046 // #region Declaration of all string's classes 3047 //************************************************************************************** 3048 local.UTF8STRING_value_block = 3049 function() 3050 { 3051 local.hex_block.call(this, arguments[0]); 3052 3053 this.is_hex_only = true; 3054 this.value = ""; // String representation of decoded ArrayBuffer 3055 }; 3056 //************************************************************************************** 3057 local.UTF8STRING_value_block.prototype = new local.hex_block(); 3058 local.UTF8STRING_value_block.constructor = local.UTF8STRING_value_block; 3059 //************************************************************************************** 3060 local.UTF8STRING_value_block.prototype.block_name = 3061 function() 3062 { 3063 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 3064 3065 return "UTF8STRING_value_block"; 3066 }; 3067 //************************************************************************************** 3068 local.UTF8STRING_value_block.prototype.toJSON = 3069 function() 3070 { 3071 /// <summary>Convertion for the block to JSON object</summary> 3072 3073 var _object = local.hex_block.prototype.toJSON.call(this); 3074 3075 _object.block_name = local.UTF8STRING_value_block.prototype.block_name.call(this); 3076 _object.value = this.value; 3077 3078 return _object; 3079 }; 3080 //************************************************************************************** 3081 in_window.org.pkijs.asn1.UTF8STRING = 3082 function() 3083 { 3084 in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]); 3085 3086 this.value_block = new local.UTF8STRING_value_block(); 3087 3088 if(arguments[0] instanceof Object) 3089 { 3090 if("value" in arguments[0]) 3091 in_window.org.pkijs.asn1.UTF8STRING.prototype.fromString.call(this,arguments[0].value); 3092 } 3093 3094 this.id_block.tag_class = 1; // UNIVERSAL 3095 this.id_block.tag_number = 12; // UTF8STRING 3096 }; 3097 //************************************************************************************** 3098 in_window.org.pkijs.asn1.UTF8STRING.prototype = new in_window.org.pkijs.asn1.ASN1_block(); 3099 in_window.org.pkijs.asn1.UTF8STRING.constructor = in_window.org.pkijs.asn1.UTF8STRING; 3100 //************************************************************************************** 3101 in_window.org.pkijs.asn1.UTF8STRING.prototype.block_name = 3102 function() 3103 { 3104 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 3105 3106 return "UTF8STRING"; 3107 }; 3108 //************************************************************************************** 3109 in_window.org.pkijs.asn1.UTF8STRING.prototype.fromBER = 3110 function(input_buffer, input_offset, input_length) 3111 { 3112 /// <summary>Base function for converting block from BER encoded array of bytes</summary> 3113 /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param> 3114 /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param> 3115 /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param> 3116 3117 var result_offset = this.value_block.fromBER(input_buffer, input_offset, (this.len_block.is_indefinite_form == true) ? input_length : this.len_block.length); 3118 if(result_offset == (-1)) 3119 { 3120 this.error = this.value_block.error; 3121 return result_offset; 3122 } 3123 3124 in_window.org.pkijs.asn1.UTF8STRING.prototype.fromBuffer.call(this, this.value_block.value_hex); 3125 3126 if(this.id_block.error.length == 0) 3127 this.block_length += this.id_block.block_length; 3128 3129 if(this.len_block.error.length == 0) 3130 this.block_length += this.len_block.block_length; 3131 3132 if(this.value_block.error.length == 0) 3133 this.block_length += this.value_block.block_length; 3134 3135 return result_offset; 3136 }; 3137 //************************************************************************************** 3138 in_window.org.pkijs.asn1.UTF8STRING.prototype.fromBuffer = 3139 function(input_buffer) 3140 { 3141 /// <param name="input_buffer" type="ArrayBuffer">Array with encoded string</param> 3142 this.value_block.value = String.fromCharCode.apply(null, new Uint8Array(input_buffer)); 3143 3144 try 3145 { 3146 this.value_block.value = decodeURIComponent(escape(this.value_block.value)); 3147 } 3148 catch(ex) 3149 { 3150 this.warnings.push("Error during \"decodeURIComponent\": " + ex + ", using raw string"); 3151 } 3152 }; 3153 //************************************************************************************** 3154 in_window.org.pkijs.asn1.UTF8STRING.prototype.fromString = 3155 function(input_string) 3156 { 3157 /// <param name="input_string" type="String">String with UNIVERSALSTRING value</param> 3158 3159 var str = unescape(encodeURIComponent(input_string)); 3160 var str_len = str.length; 3161 3162 this.value_block.value_hex = new ArrayBuffer(str_len); 3163 var view = new Uint8Array(this.value_block.value_hex); 3164 3165 for(var i = 0; i < str_len; i++) 3166 view[i] = str.charCodeAt(i); 3167 3168 this.value_block.value = input_string; 3169 }; 3170 //************************************************************************************** 3171 in_window.org.pkijs.asn1.UTF8STRING.prototype.toJSON = 3172 function() 3173 { 3174 /// <summary>Convertion for the block to JSON object</summary> 3175 3176 var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this); 3177 3178 _object.block_name = in_window.org.pkijs.asn1.UTF8STRING.prototype.block_name.call(this); 3179 3180 return _object; 3181 }; 3182 //************************************************************************************** 3183 local.BMPSTRING_value_block = 3184 function() 3185 { 3186 local.hex_block.call(this, arguments[0]); 3187 3188 this.is_hex_only = true; 3189 this.value = ""; 3190 }; 3191 //************************************************************************************** 3192 local.BMPSTRING_value_block.prototype = new local.hex_block(); 3193 local.BMPSTRING_value_block.constructor = local.BMPSTRING_value_block; 3194 //************************************************************************************** 3195 local.BMPSTRING_value_block.prototype.block_name = 3196 function() 3197 { 3198 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 3199 3200 return "BMPSTRING_value_block"; 3201 }; 3202 //************************************************************************************** 3203 local.BMPSTRING_value_block.prototype.toJSON = 3204 function() 3205 { 3206 /// <summary>Convertion for the block to JSON object</summary> 3207 3208 var _object = local.hex_block.prototype.toJSON.call(this); 3209 3210 _object.block_name = local.BMPSTRING_value_block.prototype.block_name.call(this); 3211 _object.value = this.value; 3212 3213 return _object; 3214 }; 3215 //************************************************************************************** 3216 in_window.org.pkijs.asn1.BMPSTRING = 3217 function() 3218 { 3219 in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]); 3220 3221 this.value_block = new local.BMPSTRING_value_block(); 3222 3223 if(arguments[0] instanceof Object) 3224 { 3225 if("value" in arguments[0]) 3226 in_window.org.pkijs.asn1.BMPSTRING.prototype.fromString.call(this, arguments[0].value); 3227 } 3228 3229 this.id_block.tag_class = 1; // UNIVERSAL 3230 this.id_block.tag_number = 30; // BMPSTRING 3231 }; 3232 //************************************************************************************** 3233 in_window.org.pkijs.asn1.BMPSTRING.prototype = new in_window.org.pkijs.asn1.ASN1_block(); 3234 in_window.org.pkijs.asn1.BMPSTRING.constructor = in_window.org.pkijs.asn1.BMPSTRING; 3235 //************************************************************************************** 3236 in_window.org.pkijs.asn1.BMPSTRING.prototype.block_name = 3237 function() 3238 { 3239 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 3240 3241 return "BMPSTRING"; 3242 }; 3243 //************************************************************************************** 3244 in_window.org.pkijs.asn1.BMPSTRING.prototype.fromBER = 3245 function(input_buffer, input_offset, input_length) 3246 { 3247 /// <summary>Base function for converting block from BER encoded array of bytes</summary> 3248 /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param> 3249 /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param> 3250 /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param> 3251 3252 var result_offset = this.value_block.fromBER(input_buffer, input_offset, (this.len_block.is_indefinite_form == true) ? input_length : this.len_block.length); 3253 if(result_offset == (-1)) 3254 { 3255 this.error = this.value_block.error; 3256 return result_offset; 3257 } 3258 3259 in_window.org.pkijs.asn1.BMPSTRING.prototype.fromBuffer.call(this, this.value_block.value_hex); 3260 3261 if(this.id_block.error.length == 0) 3262 this.block_length += this.id_block.block_length; 3263 3264 if(this.len_block.error.length == 0) 3265 this.block_length += this.len_block.block_length; 3266 3267 if(this.value_block.error.length == 0) 3268 this.block_length += this.value_block.block_length; 3269 3270 return result_offset; 3271 }; 3272 //************************************************************************************** 3273 in_window.org.pkijs.asn1.BMPSTRING.prototype.fromBuffer = 3274 function(input_buffer) 3275 { 3276 /// <param name="input_buffer" type="ArrayBuffer">Array with encoded string</param> 3277 3278 var copy_buffer = in_window.org.pkijs.copyBuffer(input_buffer); 3279 3280 var value_view = new Uint8Array(copy_buffer); 3281 3282 for(var i = 0; i < value_view.length; i = i + 2) 3283 { 3284 var temp = value_view[i]; 3285 3286 value_view[i] = value_view[i + 1]; 3287 value_view[i + 1] = temp; 3288 } 3289 3290 this.value_block.value = String.fromCharCode.apply(null, new Uint16Array(copy_buffer)); 3291 }; 3292 //************************************************************************************** 3293 in_window.org.pkijs.asn1.BMPSTRING.prototype.fromString = 3294 function(input_string) 3295 { 3296 /// <param name="input_string" type="String">String with UNIVERSALSTRING value</param> 3297 3298 var str_length = input_string.length; 3299 3300 this.value_block.value_hex = new ArrayBuffer(str_length * 2); 3301 var value_hex_view = new Uint8Array(this.value_block.value_hex); 3302 3303 for(var i = 0; i < str_length; i++) 3304 { 3305 var code_buf = util_tobase(input_string.charCodeAt(i), 8); 3306 var code_view = new Uint8Array(code_buf); 3307 if(code_view.length > 2) 3308 continue; 3309 3310 var dif = 2 - code_view.length; 3311 3312 for(var j = (code_view.length - 1) ; j >= 0; j--) 3313 value_hex_view[i * 2 + j + dif] = code_view[j]; 3314 } 3315 3316 this.value_block.value = input_string; 3317 }; 3318 //************************************************************************************** 3319 in_window.org.pkijs.asn1.BMPSTRING.prototype.toJSON = 3320 function() 3321 { 3322 /// <summary>Convertion for the block to JSON object</summary> 3323 3324 var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this); 3325 3326 _object.block_name = in_window.org.pkijs.asn1.BMPSTRING.prototype.block_name.call(this); 3327 3328 return _object; 3329 }; 3330 //************************************************************************************** 3331 local.UNIVERSALSTRING_value_block = 3332 function() 3333 { 3334 local.hex_block.call(this, arguments[0]); 3335 3336 this.is_hex_only = true; 3337 this.value = ""; 3338 }; 3339 //************************************************************************************** 3340 local.UNIVERSALSTRING_value_block.prototype = new local.hex_block(); 3341 local.UNIVERSALSTRING_value_block.constructor = local.UNIVERSALSTRING_value_block; 3342 //************************************************************************************** 3343 local.UNIVERSALSTRING_value_block.prototype.block_name = 3344 function() 3345 { 3346 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 3347 3348 return "UNIVERSALSTRING_value_block"; 3349 }; 3350 //************************************************************************************** 3351 local.UNIVERSALSTRING_value_block.prototype.toJSON = 3352 function() 3353 { 3354 /// <summary>Convertion for the block to JSON object</summary> 3355 3356 var _object = local.hex_block.prototype.toJSON.call(this); 3357 3358 _object.block_name = local.UNIVERSALSTRING_value_block.prototype.block_name.call(this); 3359 _object.value = this.value; 3360 3361 return _object; 3362 }; 3363 //************************************************************************************** 3364 in_window.org.pkijs.asn1.UNIVERSALSTRING = 3365 function() 3366 { 3367 in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]); 3368 3369 this.value_block = new local.UNIVERSALSTRING_value_block(); 3370 3371 if(arguments[0] instanceof Object) 3372 { 3373 if("value" in arguments[0]) 3374 in_window.org.pkijs.asn1.UNIVERSALSTRING.prototype.fromString.call(this, arguments[0].value); 3375 } 3376 3377 this.id_block.tag_class = 1; // UNIVERSAL 3378 this.id_block.tag_number = 28; // UNIVERSALSTRING 3379 }; 3380 //************************************************************************************** 3381 in_window.org.pkijs.asn1.UNIVERSALSTRING.prototype = new in_window.org.pkijs.asn1.ASN1_block(); 3382 in_window.org.pkijs.asn1.UNIVERSALSTRING.constructor = in_window.org.pkijs.asn1.UNIVERSALSTRING; 3383 //************************************************************************************** 3384 in_window.org.pkijs.asn1.UNIVERSALSTRING.prototype.block_name = 3385 function() 3386 { 3387 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 3388 3389 return "UNIVERSALSTRING"; 3390 }; 3391 //************************************************************************************** 3392 in_window.org.pkijs.asn1.UNIVERSALSTRING.prototype.fromBER = 3393 function(input_buffer, input_offset, input_length) 3394 { 3395 /// <summary>Base function for converting block from BER encoded array of bytes</summary> 3396 /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param> 3397 /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param> 3398 /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param> 3399 3400 var result_offset = this.value_block.fromBER(input_buffer, input_offset, (this.len_block.is_indefinite_form == true) ? input_length : this.len_block.length); 3401 if(result_offset == (-1)) 3402 { 3403 this.error = this.value_block.error; 3404 return result_offset; 3405 } 3406 3407 in_window.org.pkijs.asn1.UNIVERSALSTRING.prototype.fromBuffer.call(this, this.value_block.value_hex); 3408 3409 if(this.id_block.error.length == 0) 3410 this.block_length += this.id_block.block_length; 3411 3412 if(this.len_block.error.length == 0) 3413 this.block_length += this.len_block.block_length; 3414 3415 if(this.value_block.error.length == 0) 3416 this.block_length += this.value_block.block_length; 3417 3418 return result_offset; 3419 }; 3420 //************************************************************************************** 3421 in_window.org.pkijs.asn1.UNIVERSALSTRING.prototype.fromBuffer = 3422 function(input_buffer) 3423 { 3424 /// <param name="input_buffer" type="ArrayBuffer">Array with encoded string</param> 3425 3426 var copy_buffer = in_window.org.pkijs.copyBuffer(input_buffer); 3427 3428 var value_view = new Uint8Array(copy_buffer); 3429 3430 for(var i = 0; i < value_view.length; i = i + 4) 3431 { 3432 value_view[i] = value_view[i + 3]; 3433 value_view[i + 1] = value_view[i + 2]; 3434 value_view[i + 2] = 0x00; 3435 value_view[i + 3] = 0x00; 3436 } 3437 3438 this.value_block.value = String.fromCharCode.apply(null, new Uint32Array(copy_buffer)); 3439 }; 3440 //************************************************************************************** 3441 in_window.org.pkijs.asn1.UNIVERSALSTRING.prototype.fromString = 3442 function(input_string) 3443 { 3444 /// <param name="input_string" type="String">String with UNIVERSALSTRING value</param> 3445 3446 var str_length = input_string.length; 3447 3448 this.value_block.value_hex = new ArrayBuffer(str_length * 4); 3449 var value_hex_view = new Uint8Array(this.value_block.value_hex); 3450 3451 for(var i = 0; i < str_length; i++) 3452 { 3453 var code_buf = util_tobase(input_string.charCodeAt(i), 8); 3454 var code_view = new Uint8Array(code_buf); 3455 if(code_view.length > 4) 3456 continue; 3457 3458 var dif = 4 - code_view.length; 3459 3460 for(var j = (code_view.length - 1) ; j >= 0; j--) 3461 value_hex_view[i*4 + j + dif] = code_view[j]; 3462 } 3463 3464 this.value_block.value = input_string; 3465 }; 3466 //************************************************************************************** 3467 in_window.org.pkijs.asn1.UNIVERSALSTRING.prototype.toJSON = 3468 function() 3469 { 3470 /// <summary>Convertion for the block to JSON object</summary> 3471 3472 var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this); 3473 3474 _object.block_name = in_window.org.pkijs.asn1.UNIVERSALSTRING.prototype.block_name.call(this); 3475 3476 return _object; 3477 }; 3478 //************************************************************************************** 3479 local.SIMPLESTRING_value_block = 3480 function() 3481 { 3482 local.hex_block.call(this, arguments[0]); 3483 3484 /// <field type="String">Native string representation</field> 3485 this.value = ""; 3486 this.is_hex_only = true; 3487 }; 3488 //************************************************************************************** 3489 local.SIMPLESTRING_value_block.prototype = new local.hex_block(); 3490 local.SIMPLESTRING_value_block.constructor = local.SIMPLESTRING_value_block; 3491 //************************************************************************************** 3492 local.SIMPLESTRING_value_block.prototype.block_name = 3493 function() 3494 { 3495 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 3496 3497 return "SIMPLESTRING_value_block"; 3498 }; 3499 //************************************************************************************** 3500 local.SIMPLESTRING_value_block.prototype.toJSON = 3501 function() 3502 { 3503 /// <summary>Convertion for the block to JSON object</summary> 3504 3505 var _object = local.hex_block.prototype.toJSON.call(this); 3506 3507 _object.block_name = local.SIMPLESTRING_value_block.prototype.block_name.call(this); 3508 _object.value = this.value; 3509 3510 return _object; 3511 }; 3512 //************************************************************************************** 3513 local.SIMPLESTRING_block = 3514 function() 3515 { 3516 in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]); 3517 3518 this.value_block = new local.SIMPLESTRING_value_block(); 3519 3520 if(arguments[0] instanceof Object) 3521 { 3522 if("value" in arguments[0]) 3523 local.SIMPLESTRING_block.prototype.fromString.call(this, arguments[0].value); 3524 } 3525 }; 3526 //************************************************************************************** 3527 local.SIMPLESTRING_block.prototype = new in_window.org.pkijs.asn1.ASN1_block(); 3528 local.SIMPLESTRING_block.constructor = local.SIMPLESTRING_block; 3529 //************************************************************************************** 3530 local.SIMPLESTRING_block.prototype.block_name = 3531 function() 3532 { 3533 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 3534 3535 return "SIMPLESTRING"; 3536 }; 3537 //************************************************************************************** 3538 local.SIMPLESTRING_block.prototype.fromBER = 3539 function(input_buffer, input_offset, input_length) 3540 { 3541 /// <summary>Base function for converting block from BER encoded array of bytes</summary> 3542 /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param> 3543 /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param> 3544 /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param> 3545 3546 var result_offset = this.value_block.fromBER(input_buffer, input_offset, (this.len_block.is_indefinite_form == true) ? input_length : this.len_block.length); 3547 if(result_offset == (-1)) 3548 { 3549 this.error = this.value_block.error; 3550 return result_offset; 3551 } 3552 3553 local.SIMPLESTRING_block.prototype.fromBuffer.call(this, this.value_block.value_hex); 3554 3555 if(this.id_block.error.length == 0) 3556 this.block_length += this.id_block.block_length; 3557 3558 if(this.len_block.error.length == 0) 3559 this.block_length += this.len_block.block_length; 3560 3561 if(this.value_block.error.length == 0) 3562 this.block_length += this.value_block.block_length; 3563 3564 return result_offset; 3565 }; 3566 //************************************************************************************** 3567 local.SIMPLESTRING_block.prototype.fromBuffer = 3568 function(input_buffer) 3569 { 3570 /// <param name="input_buffer" type="ArrayBuffer">Array with encoded string</param> 3571 3572 this.value_block.value = String.fromCharCode.apply(null, new Uint8Array(input_buffer)); 3573 }; 3574 //************************************************************************************** 3575 local.SIMPLESTRING_block.prototype.fromString = 3576 function(input_string) 3577 { 3578 /// <param name="input_string" type="String">String with UNIVERSALSTRING value</param> 3579 var str_len = input_string.length; 3580 3581 this.value_block.value_hex = new ArrayBuffer(str_len); 3582 var view = new Uint8Array(this.value_block.value_hex); 3583 3584 for(var i = 0; i < str_len; i++) 3585 view[i] = input_string.charCodeAt(i); 3586 3587 this.value_block.value = input_string; 3588 }; 3589 //************************************************************************************** 3590 local.SIMPLESTRING_block.prototype.toJSON = 3591 function() 3592 { 3593 /// <summary>Convertion for the block to JSON object</summary> 3594 3595 var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this); 3596 3597 _object.block_name = local.SIMPLESTRING_block.prototype.block_name.call(this); 3598 3599 return _object; 3600 }; 3601 //************************************************************************************** 3602 in_window.org.pkijs.asn1.NUMERICSTRING = 3603 function() 3604 { 3605 local.SIMPLESTRING_block.call(this, arguments[0]); 3606 3607 this.id_block.tag_class = 1; // UNIVERSAL 3608 this.id_block.tag_number = 18; // NUMERICSTRING 3609 }; 3610 //************************************************************************************** 3611 in_window.org.pkijs.asn1.NUMERICSTRING.prototype = new local.SIMPLESTRING_block(); 3612 in_window.org.pkijs.asn1.NUMERICSTRING.constructor = in_window.org.pkijs.asn1.NUMERICSTRING; 3613 //************************************************************************************** 3614 in_window.org.pkijs.asn1.NUMERICSTRING.prototype.block_name = 3615 function() 3616 { 3617 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 3618 3619 return "NUMERICSTRING"; 3620 }; 3621 //************************************************************************************** 3622 in_window.org.pkijs.asn1.NUMERICSTRING.prototype.toJSON = 3623 function() 3624 { 3625 /// <summary>Convertion for the block to JSON object</summary> 3626 3627 var _object = local.SIMPLESTRING_block.prototype.toJSON.call(this); 3628 3629 _object.block_name = in_window.org.pkijs.asn1.NUMERICSTRING.prototype.block_name.call(this); 3630 3631 return _object; 3632 }; 3633 //************************************************************************************** 3634 in_window.org.pkijs.asn1.PRINTABLESTRING = 3635 function() 3636 { 3637 local.SIMPLESTRING_block.call(this, arguments[0]); 3638 3639 this.id_block.tag_class = 1; // UNIVERSAL 3640 this.id_block.tag_number = 19; // PRINTABLESTRING 3641 }; 3642 //************************************************************************************** 3643 in_window.org.pkijs.asn1.PRINTABLESTRING.prototype = new local.SIMPLESTRING_block(); 3644 in_window.org.pkijs.asn1.PRINTABLESTRING.constructor = in_window.org.pkijs.asn1.PRINTABLESTRING; 3645 //************************************************************************************** 3646 in_window.org.pkijs.asn1.PRINTABLESTRING.prototype.block_name = 3647 function() 3648 { 3649 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 3650 3651 return "PRINTABLESTRING"; 3652 }; 3653 //************************************************************************************** 3654 in_window.org.pkijs.asn1.PRINTABLESTRING.prototype.toJSON = 3655 function() 3656 { 3657 /// <summary>Convertion for the block to JSON object</summary> 3658 3659 var _object = local.SIMPLESTRING_block.prototype.toJSON.call(this); 3660 3661 _object.block_name = in_window.org.pkijs.asn1.PRINTABLESTRING.prototype.block_name.call(this); 3662 3663 return _object; 3664 }; 3665 //************************************************************************************** 3666 in_window.org.pkijs.asn1.TELETEXSTRING = 3667 function() 3668 { 3669 local.SIMPLESTRING_block.call(this, arguments[0]); 3670 3671 this.id_block.tag_class = 1; // UNIVERSAL 3672 this.id_block.tag_number = 20; // TELETEXSTRING 3673 }; 3674 //************************************************************************************** 3675 in_window.org.pkijs.asn1.TELETEXSTRING.prototype = new local.SIMPLESTRING_block(); 3676 in_window.org.pkijs.asn1.TELETEXSTRING.constructor = in_window.org.pkijs.asn1.TELETEXSTRING; 3677 //************************************************************************************** 3678 in_window.org.pkijs.asn1.TELETEXSTRING.prototype.block_name = 3679 function() 3680 { 3681 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 3682 3683 return "TELETEXSTRING"; 3684 }; 3685 //************************************************************************************** 3686 in_window.org.pkijs.asn1.TELETEXSTRING.prototype.toJSON = 3687 function() 3688 { 3689 /// <summary>Convertion for the block to JSON object</summary> 3690 3691 var _object = local.SIMPLESTRING_block.prototype.toJSON.call(this); 3692 3693 _object.block_name = in_window.org.pkijs.asn1.TELETEXSTRING.prototype.block_name.call(this); 3694 3695 return _object; 3696 }; 3697 //************************************************************************************** 3698 in_window.org.pkijs.asn1.VIDEOTEXSTRING = 3699 function() 3700 { 3701 local.SIMPLESTRING_block.call(this, arguments[0]); 3702 3703 this.id_block.tag_class = 1; // UNIVERSAL 3704 this.id_block.tag_number = 21; // VIDEOTEXSTRING 3705 }; 3706 //************************************************************************************** 3707 in_window.org.pkijs.asn1.VIDEOTEXSTRING.prototype = new local.SIMPLESTRING_block(); 3708 in_window.org.pkijs.asn1.VIDEOTEXSTRING.constructor = in_window.org.pkijs.asn1.VIDEOTEXSTRING; 3709 //************************************************************************************** 3710 in_window.org.pkijs.asn1.VIDEOTEXSTRING.prototype.block_name = 3711 function() 3712 { 3713 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 3714 3715 return "VIDEOTEXSTRING"; 3716 }; 3717 //************************************************************************************** 3718 in_window.org.pkijs.asn1.VIDEOTEXSTRING.prototype.toJSON = 3719 function() 3720 { 3721 /// <summary>Convertion for the block to JSON object</summary> 3722 3723 var _object = local.SIMPLESTRING_block.prototype.toJSON.call(this); 3724 3725 _object.block_name = in_window.org.pkijs.asn1.VIDEOTEXSTRING.prototype.block_name.call(this); 3726 3727 return _object; 3728 }; 3729 //************************************************************************************** 3730 in_window.org.pkijs.asn1.IA5STRING = 3731 function() 3732 { 3733 local.SIMPLESTRING_block.call(this, arguments[0]); 3734 3735 this.id_block.tag_class = 1; // UNIVERSAL 3736 this.id_block.tag_number = 22; // IA5STRING 3737 }; 3738 //************************************************************************************** 3739 in_window.org.pkijs.asn1.IA5STRING.prototype = new local.SIMPLESTRING_block(); 3740 in_window.org.pkijs.asn1.IA5STRING.constructor = in_window.org.pkijs.asn1.IA5STRING; 3741 //************************************************************************************** 3742 in_window.org.pkijs.asn1.IA5STRING.prototype.block_name = 3743 function() 3744 { 3745 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 3746 3747 return "IA5STRING"; 3748 }; 3749 //************************************************************************************** 3750 in_window.org.pkijs.asn1.IA5STRING.prototype.toJSON = 3751 function() 3752 { 3753 /// <summary>Convertion for the block to JSON object</summary> 3754 3755 var _object = local.SIMPLESTRING_block.prototype.toJSON.call(this); 3756 3757 _object.block_name = in_window.org.pkijs.asn1.IA5STRING.prototype.block_name.call(this); 3758 3759 return _object; 3760 }; 3761 //************************************************************************************** 3762 in_window.org.pkijs.asn1.GRAPHICSTRING = 3763 function() 3764 { 3765 local.SIMPLESTRING_block.call(this, arguments[0]); 3766 3767 this.id_block.tag_class = 1; // UNIVERSAL 3768 this.id_block.tag_number = 25; // GRAPHICSTRING 3769 }; 3770 //************************************************************************************** 3771 in_window.org.pkijs.asn1.GRAPHICSTRING.prototype = new local.SIMPLESTRING_block(); 3772 in_window.org.pkijs.asn1.GRAPHICSTRING.constructor = in_window.org.pkijs.asn1.GRAPHICSTRING; 3773 //************************************************************************************** 3774 in_window.org.pkijs.asn1.GRAPHICSTRING.prototype.block_name = 3775 function() 3776 { 3777 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 3778 3779 return "GRAPHICSTRING"; 3780 }; 3781 //************************************************************************************** 3782 in_window.org.pkijs.asn1.GRAPHICSTRING.prototype.toJSON = 3783 function() 3784 { 3785 /// <summary>Convertion for the block to JSON object</summary> 3786 3787 var _object = local.SIMPLESTRING_block.prototype.toJSON.call(this); 3788 3789 _object.block_name = in_window.org.pkijs.asn1.GRAPHICSTRING.prototype.block_name.call(this); 3790 3791 return _object; 3792 }; 3793 //************************************************************************************** 3794 in_window.org.pkijs.asn1.VISIBLESTRING = 3795 function() 3796 { 3797 local.SIMPLESTRING_block.call(this, arguments[0]); 3798 3799 this.id_block.tag_class = 1; // UNIVERSAL 3800 this.id_block.tag_number = 26; // VISIBLESTRING 3801 }; 3802 //************************************************************************************** 3803 in_window.org.pkijs.asn1.VISIBLESTRING.prototype = new local.SIMPLESTRING_block(); 3804 in_window.org.pkijs.asn1.VISIBLESTRING.constructor = in_window.org.pkijs.asn1.VISIBLESTRING; 3805 //************************************************************************************** 3806 in_window.org.pkijs.asn1.VISIBLESTRING.prototype.block_name = 3807 function() 3808 { 3809 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 3810 3811 return "VISIBLESTRING"; 3812 }; 3813 //************************************************************************************** 3814 in_window.org.pkijs.asn1.VISIBLESTRING.prototype.toJSON = 3815 function() 3816 { 3817 /// <summary>Convertion for the block to JSON object</summary> 3818 3819 var _object = local.SIMPLESTRING_block.prototype.toJSON.call(this); 3820 3821 _object.block_name = in_window.org.pkijs.asn1.VISIBLESTRING.prototype.block_name.call(this); 3822 3823 return _object; 3824 }; 3825 //************************************************************************************** 3826 in_window.org.pkijs.asn1.GENERALSTRING = 3827 function() 3828 { 3829 local.SIMPLESTRING_block.call(this, arguments[0]); 3830 3831 this.id_block.tag_class = 1; // UNIVERSAL 3832 this.id_block.tag_number = 27; // GENERALSTRING 3833 }; 3834 //************************************************************************************** 3835 in_window.org.pkijs.asn1.GENERALSTRING.prototype = new local.SIMPLESTRING_block(); 3836 in_window.org.pkijs.asn1.GENERALSTRING.constructor = in_window.org.pkijs.asn1.GENERALSTRING; 3837 //************************************************************************************** 3838 in_window.org.pkijs.asn1.GENERALSTRING.prototype.block_name = 3839 function() 3840 { 3841 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 3842 3843 return "GENERALSTRING"; 3844 }; 3845 //************************************************************************************** 3846 in_window.org.pkijs.asn1.GENERALSTRING.prototype.toJSON = 3847 function() 3848 { 3849 /// <summary>Convertion for the block to JSON object</summary> 3850 3851 var _object = local.SIMPLESTRING_block.prototype.toJSON.call(this); 3852 3853 _object.block_name = in_window.org.pkijs.asn1.GENERALSTRING.prototype.block_name.call(this); 3854 3855 return _object; 3856 }; 3857 //************************************************************************************** 3858 in_window.org.pkijs.asn1.CHARACTERSTRING = 3859 function() 3860 { 3861 local.SIMPLESTRING_block.call(this, arguments[0]); 3862 3863 this.id_block.tag_class = 1; // UNIVERSAL 3864 this.id_block.tag_number = 29; // CHARACTERSTRING 3865 }; 3866 //************************************************************************************** 3867 in_window.org.pkijs.asn1.CHARACTERSTRING.prototype = new local.SIMPLESTRING_block(); 3868 in_window.org.pkijs.asn1.CHARACTERSTRING.constructor = in_window.org.pkijs.asn1.CHARACTERSTRING; 3869 //************************************************************************************** 3870 in_window.org.pkijs.asn1.CHARACTERSTRING.prototype.block_name = 3871 function() 3872 { 3873 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 3874 3875 return "CHARACTERSTRING"; 3876 }; 3877 //************************************************************************************** 3878 in_window.org.pkijs.asn1.CHARACTERSTRING.prototype.toJSON = 3879 function() 3880 { 3881 /// <summary>Convertion for the block to JSON object</summary> 3882 3883 var _object = local.SIMPLESTRING_block.prototype.toJSON.call(this); 3884 3885 _object.block_name = in_window.org.pkijs.asn1.CHARACTERSTRING.prototype.block_name.call(this); 3886 3887 return _object; 3888 }; 3889 //************************************************************************************** 3890 // #endregion 3891 //************************************************************************************** 3892 // #region Declaration of all date and time classes 3893 //************************************************************************************** 3894 in_window.org.pkijs.asn1.UTCTIME = 3895 function() 3896 { 3897 in_window.org.pkijs.asn1.VISIBLESTRING.call(this, arguments[0]); 3898 3899 this.year = 0; 3900 this.month = 0; 3901 this.day = 0; 3902 this.hour = 0; 3903 this.minute = 0; 3904 this.second = 0; 3905 3906 // #region Create UTCTIME from ASN.1 UTC string value 3907 if((arguments[0] instanceof Object) && ("value" in arguments[0])) 3908 { 3909 in_window.org.pkijs.asn1.UTCTIME.prototype.fromString.call(this, arguments[0].value); 3910 3911 this.value_block.value_hex = new ArrayBuffer(arguments[0].value.length); 3912 var view = new Uint8Array(this.value_block.value_hex); 3913 3914 for(var i = 0; i < arguments[0].value.length; i++) 3915 view[i] = arguments[0].value.charCodeAt(i); 3916 } 3917 // #endregion 3918 // #region Create UTCTIME from JavaScript Date type 3919 if((arguments[0] instanceof Object) && ("value_date" in arguments[0])) 3920 { 3921 in_window.org.pkijs.asn1.UTCTIME.prototype.fromDate.call(this, arguments[0].value_date); 3922 this.value_block.value_hex = in_window.org.pkijs.asn1.UTCTIME.prototype.toBuffer.call(this); 3923 } 3924 // #endregion 3925 3926 this.id_block.tag_class = 1; // UNIVERSAL 3927 this.id_block.tag_number = 23; // UTCTIME 3928 }; 3929 //************************************************************************************** 3930 in_window.org.pkijs.asn1.UTCTIME.prototype = new in_window.org.pkijs.asn1.VISIBLESTRING(); 3931 in_window.org.pkijs.asn1.UTCTIME.constructor = in_window.org.pkijs.asn1.UTCTIME; 3932 //************************************************************************************** 3933 in_window.org.pkijs.asn1.UTCTIME.prototype.fromBER = 3934 function(input_buffer, input_offset, input_length) 3935 { 3936 /// <summary>Base function for converting block from BER encoded array of bytes</summary> 3937 /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param> 3938 /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param> 3939 /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param> 3940 3941 var result_offset = this.value_block.fromBER(input_buffer, input_offset, (this.len_block.is_indefinite_form == true) ? input_length : this.len_block.length); 3942 if(result_offset == (-1)) 3943 { 3944 this.error = this.value_block.error; 3945 return result_offset; 3946 } 3947 3948 in_window.org.pkijs.asn1.UTCTIME.prototype.fromBuffer.call(this, this.value_block.value_hex); 3949 3950 if(this.id_block.error.length == 0) 3951 this.block_length += this.id_block.block_length; 3952 3953 if(this.len_block.error.length == 0) 3954 this.block_length += this.len_block.block_length; 3955 3956 if(this.value_block.error.length == 0) 3957 this.block_length += this.value_block.block_length; 3958 3959 return result_offset; 3960 }; 3961 //************************************************************************************** 3962 in_window.org.pkijs.asn1.UTCTIME.prototype.fromBuffer = 3963 function(input_buffer) 3964 { 3965 in_window.org.pkijs.asn1.UTCTIME.prototype.fromString.call(this, String.fromCharCode.apply(null, new Uint8Array(input_buffer))); 3966 }; 3967 //************************************************************************************** 3968 in_window.org.pkijs.asn1.UTCTIME.prototype.toBuffer = 3969 function() 3970 { 3971 var str = in_window.org.pkijs.asn1.UTCTIME.prototype.toString.call(this); 3972 3973 var buffer = new ArrayBuffer(str.length); 3974 var view = new Uint8Array(buffer); 3975 3976 for(var i = 0; i < str.length; i++) 3977 view[i] = str.charCodeAt(i); 3978 3979 return buffer; 3980 }; 3981 //************************************************************************************** 3982 in_window.org.pkijs.asn1.UTCTIME.prototype.fromDate = 3983 function(input_date) 3984 { 3985 /// <summary>Create "UTCTime" ASN.1 type from JavaScript "Date" type</summary> 3986 3987 this.year = input_date.getUTCFullYear(); 3988 this.month = input_date.getUTCMonth() + 1; 3989 this.day = input_date.getUTCDate(); 3990 this.hour = input_date.getUTCHours(); 3991 this.minute = input_date.getUTCMinutes(); 3992 this.second = input_date.getUTCSeconds(); 3993 }; 3994 //************************************************************************************** 3995 in_window.org.pkijs.asn1.UTCTIME.prototype.toDate = 3996 function() 3997 { 3998 return (new Date(Date.UTC(this.year, this.month - 1, this.day, this.hour, this.minute, this.second))); 3999 }; 4000 //************************************************************************************** 4001 in_window.org.pkijs.asn1.UTCTIME.prototype.fromString = 4002 function(input_string) 4003 { 4004 /// <summary>Create "UTCTime" ASN.1 type from JavaScript "String" type</summary> 4005 4006 // #region Parse input string 4007 var parser = /(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})Z/ig; 4008 var parser_array = parser.exec(input_string); 4009 if(parser_array === null) 4010 { 4011 this.error = "Wrong input string for convertion"; 4012 return; 4013 } 4014 // #endregion 4015 4016 // #region Store parsed values 4017 var year = parseInt(parser_array[1], 10); 4018 if(year >= 50) 4019 this.year = 1900 + year; 4020 else 4021 this.year = 2000 + year; 4022 4023 this.month = parseInt(parser_array[2], 10); 4024 this.day = parseInt(parser_array[3], 10); 4025 this.hour = parseInt(parser_array[4], 10); 4026 this.minute = parseInt(parser_array[5], 10); 4027 this.second = parseInt(parser_array[6], 10); 4028 // #endregion 4029 }; 4030 //************************************************************************************** 4031 in_window.org.pkijs.asn1.UTCTIME.prototype.toString = 4032 function() 4033 { 4034 var output_array = new Array(7); 4035 4036 output_array[0] = in_window.org.pkijs.padNumber(((this.year < 2000) ? (this.year - 1900) : (this.year - 2000)), 2); 4037 output_array[1] = in_window.org.pkijs.padNumber(this.month, 2); 4038 output_array[2] = in_window.org.pkijs.padNumber(this.day, 2); 4039 output_array[3] = in_window.org.pkijs.padNumber(this.hour, 2); 4040 output_array[4] = in_window.org.pkijs.padNumber(this.minute, 2); 4041 output_array[5] = in_window.org.pkijs.padNumber(this.second, 2); 4042 output_array[6] = "Z"; 4043 4044 return output_array.join(''); 4045 }; 4046 //************************************************************************************** 4047 in_window.org.pkijs.asn1.UTCTIME.prototype.block_name = 4048 function() 4049 { 4050 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 4051 4052 return "UTCTIME"; 4053 }; 4054 //************************************************************************************** 4055 in_window.org.pkijs.asn1.UTCTIME.prototype.toJSON = 4056 function() 4057 { 4058 /// <summary>Convertion for the block to JSON object</summary> 4059 4060 var _object = in_window.org.pkijs.asn1.VISIBLESTRING.prototype.toJSON.call(this); 4061 4062 _object.block_name = in_window.org.pkijs.asn1.UTCTIME.prototype.block_name.call(this); 4063 _object.year = this.year; 4064 _object.month = this.month; 4065 _object.day = this.day; 4066 _object.hour = this.hour; 4067 _object.minute = this.minute; 4068 _object.second = this.second; 4069 4070 return _object; 4071 }; 4072 //************************************************************************************** 4073 in_window.org.pkijs.asn1.GENERALIZEDTIME = 4074 function() 4075 { 4076 in_window.org.pkijs.asn1.VISIBLESTRING.call(this, arguments[0]); 4077 4078 this.year = 0; 4079 this.month = 0; 4080 this.day = 0; 4081 this.hour = 0; 4082 this.minute = 0; 4083 this.second = 0; 4084 this.millisecond = 0; 4085 4086 // #region Create GeneralizedTime from ASN.1 string value 4087 if((arguments[0] instanceof Object) && ("value" in arguments[0])) 4088 { 4089 in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.fromString.call(this, arguments[0].value); 4090 4091 this.value_block.value_hex = new ArrayBuffer(arguments[0].value.length); 4092 var view = new Uint8Array(this.value_block.value_hex); 4093 4094 for(var i = 0; i < arguments[0].value.length; i++) 4095 view[i] = arguments[0].value.charCodeAt(i); 4096 } 4097 // #endregion 4098 // #region Create GeneralizedTime from JavaScript Date type 4099 if((arguments[0] instanceof Object) && ("value_date" in arguments[0])) 4100 { 4101 in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.fromDate.call(this, arguments[0].value_date); 4102 this.value_block.value_hex = in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.toBuffer.call(this); 4103 } 4104 // #endregion 4105 4106 this.id_block.tag_class = 1; // UNIVERSAL 4107 this.id_block.tag_number = 24; // GENERALIZEDTIME 4108 }; 4109 //************************************************************************************** 4110 in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype = new in_window.org.pkijs.asn1.VISIBLESTRING(); 4111 in_window.org.pkijs.asn1.GENERALIZEDTIME.constructor = in_window.org.pkijs.asn1.GENERALIZEDTIME; 4112 //************************************************************************************** 4113 in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.fromBER = 4114 function(input_buffer, input_offset, input_length) 4115 { 4116 /// <summary>Base function for converting block from BER encoded array of bytes</summary> 4117 /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param> 4118 /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param> 4119 /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param> 4120 4121 var result_offset = this.value_block.fromBER(input_buffer, input_offset, (this.len_block.is_indefinite_form == true) ? input_length : this.len_block.length); 4122 if(result_offset == (-1)) 4123 { 4124 this.error = this.value_block.error; 4125 return result_offset; 4126 } 4127 4128 in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.fromBuffer.call(this, this.value_block.value_hex); 4129 4130 if(this.id_block.error.length == 0) 4131 this.block_length += this.id_block.block_length; 4132 4133 if(this.len_block.error.length == 0) 4134 this.block_length += this.len_block.block_length; 4135 4136 if(this.value_block.error.length == 0) 4137 this.block_length += this.value_block.block_length; 4138 4139 return result_offset; 4140 }; 4141 //************************************************************************************** 4142 in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.fromBuffer = 4143 function(input_buffer) 4144 { 4145 in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.fromString.call(this, String.fromCharCode.apply(null, new Uint8Array(input_buffer))); 4146 }; 4147 //************************************************************************************** 4148 in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.toBuffer = 4149 function() 4150 { 4151 var str = in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.toString.call(this); 4152 4153 var buffer = new ArrayBuffer(str.length); 4154 var view = new Uint8Array(buffer); 4155 4156 for(var i = 0; i < str.length; i++) 4157 view[i] = str.charCodeAt(i); 4158 4159 return buffer; 4160 }; 4161 //************************************************************************************** 4162 in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.fromDate = 4163 function(input_date) 4164 { 4165 /// <summary>Create "GeneralizedTime" ASN.1 type from JavaScript "Date" type</summary> 4166 4167 this.year = input_date.getUTCFullYear(); 4168 this.month = input_date.getUTCMonth(); 4169 this.day = input_date.getUTCDate(); 4170 this.hour = input_date.getUTCHours(); 4171 this.minute = input_date.getUTCMinutes(); 4172 this.second = input_date.getUTCSeconds(); 4173 this.millisecond = input_date.getUTCMilliseconds(); 4174 }; 4175 //************************************************************************************** 4176 in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.toDate = 4177 function() 4178 { 4179 return (new Date(Date.UTC(this.year, this.month - 1, this.day, this.hour, this.minute, this.second, this.millisecond))); 4180 }; 4181 //************************************************************************************** 4182 in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.fromString = 4183 function(input_string) 4184 { 4185 /// <summary>Create "GeneralizedTime" ASN.1 type from JavaScript "String" type</summary> 4186 4187 // #region Initial variables 4188 var isUTC = false; 4189 4190 var timeString = ""; 4191 var dateTimeString = ""; 4192 var fractionPart = 0; 4193 4194 var parser; 4195 4196 var hourDifference = 0; 4197 var minuteDifference = 0; 4198 // #endregion 4199 4200 // #region Convert as UTC time 4201 if(input_string[input_string.length - 1] == "Z") 4202 { 4203 timeString = input_string.substr(0, input_string.length - 1); 4204 4205 isUTC = true; 4206 } 4207 // #endregion 4208 // #region Convert as local time 4209 else 4210 { 4211 var number = new Number(input_string[input_string.length - 1]); 4212 4213 if(isNaN(number.valueOf())) 4214 throw new Error("Wrong input string for convertion"); 4215 4216 timeString = input_string; 4217 } 4218 // #endregion 4219 4220 // #region Check that we do not have a "+" and "-" symbols inside UTC time 4221 if(isUTC) 4222 { 4223 if(timeString.indexOf("+") != (-1)) 4224 throw new Error("Wrong input string for convertion"); 4225 4226 if(timeString.indexOf("-") != (-1)) 4227 throw new Error("Wrong input string for convertion"); 4228 } 4229 // #endregion 4230 // #region Get "UTC time difference" in case of local time 4231 else 4232 { 4233 var multiplier = 1; 4234 var differencePosition = timeString.indexOf("+"); 4235 var differenceString = ""; 4236 4237 if(differencePosition == (-1)) 4238 { 4239 differencePosition = timeString.indexOf("-"); 4240 multiplier = (-1); 4241 } 4242 4243 if(differencePosition != (-1)) 4244 { 4245 differenceString = timeString.substr(differencePosition + 1); 4246 timeString = timeString.substr(0, differencePosition); 4247 4248 if((differenceString.length != 2) && (differenceString.length != 4)) 4249 throw new Error("Wrong input string for convertion"); 4250 4251 var number = new Number(differenceString.substr(0, 2)); 4252 4253 if(isNaN(number.valueOf())) 4254 throw new Error("Wrong input string for convertion"); 4255 4256 hourDifference = multiplier * number; 4257 4258 if(differenceString.length == 4) 4259 { 4260 number = new Number(differenceString.substr(2, 2)); 4261 4262 if(isNaN(number.valueOf())) 4263 throw new Error("Wrong input string for convertion"); 4264 4265 minuteDifference = multiplier * number; 4266 } 4267 } 4268 } 4269 // #endregion 4270 4271 // #region Get position of fraction point 4272 var fractionPointPosition = timeString.indexOf("."); // Check for "full stop" symbol 4273 if(fractionPointPosition == (-1)) 4274 fractionPointPosition = timeString.indexOf(","); // Check for "comma" symbol 4275 // #endregion 4276 4277 // #region Get fraction part 4278 if(fractionPointPosition != (-1)) 4279 { 4280 var fractionPartCheck = new Number("0" + timeString.substr(fractionPointPosition)); 4281 4282 if(isNaN(fractionPartCheck.valueOf())) 4283 throw new Error("Wrong input string for convertion"); 4284 4285 fractionPart = fractionPartCheck.valueOf(); 4286 4287 dateTimeString = timeString.substr(0, fractionPointPosition); 4288 } 4289 else 4290 dateTimeString = timeString; 4291 // #endregion 4292 4293 // #region Parse internal date 4294 switch(true) 4295 { 4296 case (dateTimeString.length == 8): // "YYYYMMDD" 4297 parser = /(\d{4})(\d{2})(\d{2})/ig; 4298 if(fractionPointPosition !== (-1)) 4299 throw new Error("Wrong input string for convertion"); // Here we should not have a "fraction point" 4300 break; 4301 case (dateTimeString.length == 10): // "YYYYMMDDHH" 4302 parser = /(\d{4})(\d{2})(\d{2})(\d{2})/ig; 4303 4304 if(fractionPointPosition !== (-1)) 4305 { 4306 var fractionResult = 60 * fractionPart; 4307 this.minute = Math.floor(fractionResult); 4308 4309 fractionResult = 60 * (fractionResult - this.minute); 4310 this.second = Math.floor(fractionResult); 4311 4312 fractionResult = 1000 * (fractionResult - this.second); 4313 this.millisecond = Math.floor(fractionResult); 4314 } 4315 break; 4316 case (dateTimeString.length == 12): // "YYYYMMDDHHMM" 4317 parser = /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})/ig; 4318 4319 if(fractionPointPosition !== (-1)) 4320 { 4321 var fractionResult = 60 * fractionPart; 4322 this.second = Math.floor(fractionResult); 4323 4324 fractionResult = 1000 * (fractionResult - this.second); 4325 this.millisecond = Math.floor(fractionResult); 4326 } 4327 break; 4328 case (dateTimeString.length == 14): // "YYYYMMDDHHMMSS" 4329 parser = /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/ig; 4330 4331 if(fractionPointPosition !== (-1)) 4332 { 4333 var fractionResult = 1000 * fractionPart; 4334 this.millisecond = Math.floor(fractionResult); 4335 } 4336 break; 4337 default: 4338 throw new Error("Wrong input string for convertion"); 4339 } 4340 // #endregion 4341 4342 // #region Put parsed values at right places 4343 var parser_array = parser.exec(dateTimeString); 4344 if(parser_array == null) 4345 throw new Error("Wrong input string for convertion"); 4346 4347 for(var j = 1; j < parser_array.length; j++) 4348 { 4349 switch(j) 4350 { 4351 case 1: 4352 this.year = parseInt(parser_array[j], 10); 4353 break; 4354 case 2: 4355 this.month = parseInt(parser_array[j], 10) - 1; // In JavaScript we have month range as "0 - 11" 4356 break; 4357 case 3: 4358 this.day = parseInt(parser_array[j], 10); 4359 break; 4360 case 4: 4361 this.hour = parseInt(parser_array[j], 10) + hourDifference; 4362 break; 4363 case 5: 4364 this.minute = parseInt(parser_array[j], 10) + minuteDifference; 4365 break; 4366 case 6: 4367 this.second = parseInt(parser_array[j], 10); 4368 break; 4369 default: 4370 throw new Error("Wrong input string for convertion"); 4371 } 4372 } 4373 // #endregion 4374 4375 // #region Get final date 4376 if(isUTC == false) 4377 { 4378 var tempDate = new Date(this.year, this.month, this.day, this.hour, this.minute, this.second, this.millisecond); 4379 4380 this.year = tempDate.getUTCFullYear(); 4381 this.month = tempDate.getUTCMonth(); 4382 this.day = tempDate.getUTCDay(); 4383 this.hour = tempDate.getUTCHours(); 4384 this.minute = tempDate.getUTCMinutes(); 4385 this.second = tempDate.getUTCSeconds(); 4386 this.millisecond = tempDate.getUTCMilliseconds(); 4387 } 4388 // #endregion 4389 }; 4390 //************************************************************************************** 4391 in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.toString = 4392 function() 4393 { 4394 var output_array = new Array(); 4395 4396 output_array.push(in_window.org.pkijs.padNumber(this.year, 4)); 4397 output_array.push(in_window.org.pkijs.padNumber(this.month, 2)); 4398 output_array.push(in_window.org.pkijs.padNumber(this.day, 2)); 4399 output_array.push(in_window.org.pkijs.padNumber(this.hour, 2)); 4400 output_array.push(in_window.org.pkijs.padNumber(this.minute, 2)); 4401 output_array.push(in_window.org.pkijs.padNumber(this.second, 2)); 4402 if(this.millisecond != 0) 4403 { 4404 output_array.push("."); 4405 output_array.push(in_window.org.pkijs.padNumber(this.millisecond, 3)); 4406 } 4407 output_array.push("Z"); 4408 4409 return output_array.join(''); 4410 }; 4411 //************************************************************************************** 4412 in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.block_name = 4413 function() 4414 { 4415 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 4416 4417 return "GENERALIZEDTIME"; 4418 }; 4419 //************************************************************************************** 4420 in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.toJSON = 4421 function() 4422 { 4423 /// <summary>Convertion for the block to JSON object</summary> 4424 4425 var _object = in_window.org.pkijs.asn1.VISIBLESTRING.prototype.toJSON.call(this); 4426 4427 _object.block_name = in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.block_name.call(this); 4428 _object.year = this.year; 4429 _object.month = this.month; 4430 _object.day = this.day; 4431 _object.hour = this.hour; 4432 _object.minute = this.minute; 4433 _object.second = this.second; 4434 _object.millisecond = this.millisecond; 4435 4436 return _object; 4437 }; 4438 //************************************************************************************** 4439 in_window.org.pkijs.asn1.DATE = 4440 function() 4441 { 4442 in_window.org.pkijs.asn1.UTF8STRING.call(this, arguments[0]); 4443 4444 this.id_block.tag_class = 1; // UNIVERSAL 4445 this.id_block.tag_number = 31; // DATE 4446 }; 4447 //************************************************************************************** 4448 in_window.org.pkijs.asn1.DATE.prototype = new in_window.org.pkijs.asn1.UTF8STRING(); 4449 in_window.org.pkijs.asn1.DATE.constructor = in_window.org.pkijs.asn1.DATE; 4450 //************************************************************************************** 4451 in_window.org.pkijs.asn1.DATE.prototype.block_name = 4452 function() 4453 { 4454 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 4455 4456 return "DATE"; 4457 }; 4458 //************************************************************************************** 4459 in_window.org.pkijs.asn1.DATE.prototype.toJSON = 4460 function() 4461 { 4462 /// <summary>Convertion for the block to JSON object</summary> 4463 4464 var _object = in_window.org.pkijs.asn1.UTF8STRING.prototype.toJSON.call(this); 4465 4466 _object.block_name = in_window.org.pkijs.asn1.DATE.prototype.block_name.call(this); 4467 4468 return _object; 4469 }; 4470 //************************************************************************************** 4471 in_window.org.pkijs.asn1.TIMEOFDAY = 4472 function() 4473 { 4474 in_window.org.pkijs.asn1.UTF8STRING.call(this, arguments[0]); 4475 4476 this.id_block.tag_class = 1; // UNIVERSAL 4477 this.id_block.tag_number = 32; // TIMEOFDAY 4478 }; 4479 //************************************************************************************** 4480 in_window.org.pkijs.asn1.TIMEOFDAY.prototype = new in_window.org.pkijs.asn1.UTF8STRING(); 4481 in_window.org.pkijs.asn1.TIMEOFDAY.constructor = in_window.org.pkijs.asn1.TIMEOFDAY; 4482 //************************************************************************************** 4483 in_window.org.pkijs.asn1.TIMEOFDAY.prototype.block_name = 4484 function() 4485 { 4486 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 4487 4488 return "TIMEOFDAY"; 4489 }; 4490 //************************************************************************************** 4491 in_window.org.pkijs.asn1.TIMEOFDAY.prototype.toJSON = 4492 function() 4493 { 4494 /// <summary>Convertion for the block to JSON object</summary> 4495 4496 var _object = in_window.org.pkijs.asn1.UTF8STRING.prototype.toJSON.call(this); 4497 4498 _object.block_name = in_window.org.pkijs.asn1.TIMEOFDAY.prototype.block_name.call(this); 4499 4500 return _object; 4501 }; 4502 //************************************************************************************** 4503 in_window.org.pkijs.asn1.DATETIME = 4504 function() 4505 { 4506 in_window.org.pkijs.asn1.UTF8STRING.call(this, arguments[0]); 4507 4508 this.id_block.tag_class = 1; // UNIVERSAL 4509 this.id_block.tag_number = 33; // DATETIME 4510 }; 4511 //************************************************************************************** 4512 in_window.org.pkijs.asn1.DATETIME.prototype = new in_window.org.pkijs.asn1.UTF8STRING(); 4513 in_window.org.pkijs.asn1.DATETIME.constructor = in_window.org.pkijs.asn1.DATETIME; 4514 //************************************************************************************** 4515 in_window.org.pkijs.asn1.DATETIME.prototype.block_name = 4516 function() 4517 { 4518 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 4519 4520 return "DATETIME"; 4521 }; 4522 //************************************************************************************** 4523 in_window.org.pkijs.asn1.DATETIME.prototype.toJSON = 4524 function() 4525 { 4526 /// <summary>Convertion for the block to JSON object</summary> 4527 4528 var _object = in_window.org.pkijs.asn1.UTF8STRING.prototype.toJSON.call(this); 4529 4530 _object.block_name = in_window.org.pkijs.asn1.DATETIME.prototype.block_name.call(this); 4531 4532 return _object; 4533 }; 4534 //************************************************************************************** 4535 in_window.org.pkijs.asn1.DURATION = 4536 function() 4537 { 4538 in_window.org.pkijs.asn1.UTF8STRING.call(this, arguments[0]); 4539 4540 this.id_block.tag_class = 1; // UNIVERSAL 4541 this.id_block.tag_number = 34; // DURATION 4542 }; 4543 //************************************************************************************** 4544 in_window.org.pkijs.asn1.DURATION.prototype = new in_window.org.pkijs.asn1.UTF8STRING(); 4545 in_window.org.pkijs.asn1.DURATION.constructor = in_window.org.pkijs.asn1.DURATION; 4546 //************************************************************************************** 4547 in_window.org.pkijs.asn1.DURATION.prototype.block_name = 4548 function() 4549 { 4550 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 4551 4552 return "DURATION"; 4553 }; 4554 //************************************************************************************** 4555 in_window.org.pkijs.asn1.DURATION.prototype.toJSON = 4556 function() 4557 { 4558 /// <summary>Convertion for the block to JSON object</summary> 4559 4560 var _object = in_window.org.pkijs.asn1.UTF8STRING.prototype.toJSON.call(this); 4561 4562 _object.block_name = in_window.org.pkijs.asn1.DURATION.prototype.block_name.call(this); 4563 4564 return _object; 4565 }; 4566 //************************************************************************************** 4567 in_window.org.pkijs.asn1.TIME = 4568 function() 4569 { 4570 in_window.org.pkijs.asn1.UTF8STRING.call(this, arguments[0]); 4571 4572 this.id_block.tag_class = 1; // UNIVERSAL 4573 this.id_block.tag_number = 14; // TIME 4574 }; 4575 //************************************************************************************** 4576 in_window.org.pkijs.asn1.TIME.prototype = new in_window.org.pkijs.asn1.UTF8STRING(); 4577 in_window.org.pkijs.asn1.TIME.constructor = in_window.org.pkijs.asn1.TIME; 4578 //************************************************************************************** 4579 in_window.org.pkijs.asn1.TIME.prototype.block_name = 4580 function() 4581 { 4582 /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary> 4583 4584 return "TIME"; 4585 }; 4586 //************************************************************************************** 4587 in_window.org.pkijs.asn1.TIME.prototype.toJSON = 4588 function() 4589 { 4590 /// <summary>Convertion for the block to JSON object</summary> 4591 4592 var _object = in_window.org.pkijs.asn1.UTF8STRING.prototype.toJSON.call(this); 4593 4594 _object.block_name = in_window.org.pkijs.asn1.TIME.prototype.block_name.call(this); 4595 4596 return _object; 4597 }; 4598 //************************************************************************************** 4599 // #endregion 4600 //************************************************************************************** 4601 // #region Declaration of special ASN.1 schema type CHOICE 4602 //************************************************************************************** 4603 in_window.org.pkijs.asn1.CHOICE = 4604 function() 4605 { 4606 if(arguments[0] instanceof Object) 4607 { 4608 this.value = in_window.org.pkijs.getValue(arguments[0], "value", new Array()); // Array of ASN.1 types for make a choice from 4609 this.optional = in_window.org.pkijs.getValue(arguments[0], "optional", false); 4610 } 4611 }; 4612 //************************************************************************************** 4613 // #endregion 4614 //************************************************************************************** 4615 // #region Declaration of special ASN.1 schema type ANY 4616 //************************************************************************************** 4617 in_window.org.pkijs.asn1.ANY = 4618 function() 4619 { 4620 if(arguments[0] instanceof Object) 4621 { 4622 this.name = in_window.org.pkijs.getValue(arguments[0], "name", ""); 4623 this.optional = in_window.org.pkijs.getValue(arguments[0], "optional", false); 4624 } 4625 }; 4626 //************************************************************************************** 4627 // #endregion 4628 //************************************************************************************** 4629 // #region Declaration of special ASN.1 schema type REPEATED 4630 //************************************************************************************** 4631 in_window.org.pkijs.asn1.REPEATED = 4632 function() 4633 { 4634 if(arguments[0] instanceof Object) 4635 { 4636 this.name = in_window.org.pkijs.getValue(arguments[0], "name", ""); 4637 this.optional = in_window.org.pkijs.getValue(arguments[0], "optional", false); 4638 this.value = in_window.org.pkijs.getValue(arguments[0], "value", new in_window.org.pkijs.asn1.ANY()); 4639 this.local = in_window.org.pkijs.getValue(arguments[0], "local", false); // Could local or global array to store elements 4640 } 4641 }; 4642 //************************************************************************************** 4643 // #endregion 4644 //************************************************************************************** 4645 // #region Major ASN.1 BER decoding function 4646 //************************************************************************************** 4647 function fromBER_raw(input_buffer, input_offset, input_length) 4648 { 4649 var incoming_offset = input_offset; // Need to store initial offset since "input_offset" is changing in the function 4650 4651 // #region Local function changing a type for ASN.1 classes 4652 function local_change_type(input_object, new_type) 4653 { 4654 if(input_object instanceof new_type) 4655 return input_object; 4656 4657 var new_object = new new_type(); 4658 new_object.id_block = input_object.id_block; 4659 new_object.len_block = input_object.len_block; 4660 new_object.warnings = input_object.warnings; 4661 new_object.value_before_decode = util_copybuf(input_object.value_before_decode); 4662 4663 return new_object; 4664 } 4665 // #endregion 4666 4667 // #region Create a basic ASN.1 type since we need to return errors and warnings from the function 4668 var return_object = new in_window.org.pkijs.asn1.ASN1_block(); 4669 // #endregion 4670 4671 // #region Basic check for parameters 4672 if(check_buffer_params(input_buffer, input_offset, input_length) === false) 4673 { 4674 return_object.error = "Wrong input parameters"; 4675 return { 4676 offset: (-1), 4677 result: return_object 4678 }; 4679 } 4680 // #endregion 4681 4682 // #region Getting Uint8Array from ArrayBuffer 4683 var int_buffer = new Uint8Array(input_buffer, input_offset, input_length); 4684 // #endregion 4685 4686 // #region Initial checks 4687 if(int_buffer.length == 0) 4688 { 4689 this.error = "Zero buffer length"; 4690 return { 4691 offset: (-1), 4692 result: return_object 4693 }; 4694 } 4695 // #endregion 4696 4697 // #region Decode indentifcation block of ASN.1 BER structure 4698 var result_offset = return_object.id_block.fromBER(input_buffer, input_offset, input_length); 4699 return_object.warnings.concat(return_object.id_block.warnings); 4700 if(result_offset == (-1)) 4701 { 4702 return_object.error = return_object.id_block.error; 4703 return { 4704 offset: (-1), 4705 result: return_object 4706 }; 4707 } 4708 4709 input_offset = result_offset; 4710 input_length -= return_object.id_block.block_length; 4711 // #endregion 4712 4713 // #region Decode length block of ASN.1 BER structure 4714 result_offset = return_object.len_block.fromBER(input_buffer, input_offset, input_length); 4715 return_object.warnings.concat(return_object.len_block.warnings); 4716 if(result_offset == (-1)) 4717 { 4718 return_object.error = return_object.len_block.error; 4719 return { 4720 offset: (-1), 4721 result: return_object 4722 }; 4723 } 4724 4725 input_offset = result_offset; 4726 input_length -= return_object.len_block.block_length; 4727 // #endregion 4728 4729 // #region Check for usign indefinite length form in encoding for primitive types 4730 if((return_object.id_block.is_constructed == false) && 4731 (return_object.len_block.is_indefinite_form == true)) 4732 { 4733 return_object.error = new String("Indefinite length form used for primitive encoding form"); 4734 return { 4735 offset: (-1), 4736 result: return_object 4737 }; 4738 } 4739 // #endregion 4740 4741 // #region Switch ASN.1 block type 4742 var new_asn1_type = in_window.org.pkijs.asn1.ASN1_block; 4743 4744 switch(return_object.id_block.tag_class) 4745 { 4746 // #region UNIVERSAL 4747 case 1: 4748 // #region Check for reserved tag numbers 4749 if((return_object.id_block.tag_number >= 37) && 4750 (return_object.id_block.is_hex_only == false)) 4751 { 4752 return_object.error = "UNIVERSAL 37 and upper tags are reserved by ASN.1 standard"; 4753 return { 4754 offset: (-1), 4755 result: return_object 4756 }; 4757 } 4758 // #endregion 4759 4760 switch(return_object.id_block.tag_number) 4761 { 4762 // #region EOC type 4763 case 0: 4764 // #region Check for EOC type 4765 if((return_object.id_block.is_constructed == true) && 4766 (return_object.len_block.length > 0)) 4767 { 4768 return_object.error = "Type [UNIVERSAL 0] is reserved"; 4769 return { 4770 offset: (-1), 4771 result: return_object 4772 }; 4773 } 4774 // #endregion 4775 4776 new_asn1_type = in_window.org.pkijs.asn1.EOC; 4777 4778 break; 4779 // #endregion 4780 // #region BOOLEAN type 4781 case 1: 4782 new_asn1_type = in_window.org.pkijs.asn1.BOOLEAN; 4783 break; 4784 // #endregion 4785 // #region INTEGER type 4786 case 2: 4787 new_asn1_type = in_window.org.pkijs.asn1.INTEGER; 4788 break; 4789 // #endregion 4790 // #region BITSTRING type 4791 case 3: 4792 new_asn1_type = in_window.org.pkijs.asn1.BITSTRING; 4793 break; 4794 // #endregion 4795 // #region OCTETSTRING type 4796 case 4: 4797 new_asn1_type = in_window.org.pkijs.asn1.OCTETSTRING; 4798 break; 4799 // #endregion 4800 // #region NULL type 4801 case 5: 4802 new_asn1_type = in_window.org.pkijs.asn1.NULL; 4803 break; 4804 // #endregion 4805 // #region OBJECT IDENTIFIER type 4806 case 6: 4807 new_asn1_type = in_window.org.pkijs.asn1.OID; 4808 break; 4809 // #endregion 4810 // #region ENUMERATED type 4811 case 10: 4812 new_asn1_type = in_window.org.pkijs.asn1.ENUMERATED; 4813 break; 4814 // #endregion 4815 // #region UTF8STRING type 4816 case 12: 4817 new_asn1_type = in_window.org.pkijs.asn1.UTF8STRING; 4818 break; 4819 // #endregion 4820 // #region TIME type 4821 case 14: 4822 new_asn1_type = in_window.org.pkijs.asn1.TIME; 4823 break; 4824 // #endregion 4825 // #region ASN.1 reserved type 4826 case 15: 4827 return_object.error = "[UNIVERSAL 15] is reserved by ASN.1 standard"; 4828 return { 4829 offset: (-1), 4830 result: return_object 4831 }; 4832 break; 4833 // #endregion 4834 // #region SEQUENCE type 4835 case 16: 4836 new_asn1_type = in_window.org.pkijs.asn1.SEQUENCE; 4837 break; 4838 // #endregion 4839 // #region SET type 4840 case 17: 4841 new_asn1_type = in_window.org.pkijs.asn1.SET; 4842 break; 4843 // #endregion 4844 // #region NUMERICSTRING type 4845 case 18: 4846 new_asn1_type = in_window.org.pkijs.asn1.NUMERICSTRING; 4847 break; 4848 // #endregion 4849 // #region PRINTABLESTRING type 4850 case 19: 4851 new_asn1_type = in_window.org.pkijs.asn1.PRINTABLESTRING; 4852 break; 4853 // #endregion 4854 // #region TELETEXSTRING type 4855 case 20: 4856 new_asn1_type = in_window.org.pkijs.asn1.TELETEXSTRING; 4857 break; 4858 // #endregion 4859 // #region VIDEOTEXSTRING type 4860 case 21: 4861 new_asn1_type = in_window.org.pkijs.asn1.VIDEOTEXSTRING; 4862 break; 4863 // #endregion 4864 // #region IA5STRING type 4865 case 22: 4866 new_asn1_type = in_window.org.pkijs.asn1.IA5STRING; 4867 break; 4868 // #endregion 4869 // #region UTCTIME type 4870 case 23: 4871 new_asn1_type = in_window.org.pkijs.asn1.UTCTIME; 4872 break; 4873 // #endregion 4874 // #region GENERALIZEDTIME type 4875 case 24: 4876 new_asn1_type = in_window.org.pkijs.asn1.GENERALIZEDTIME; 4877 break; 4878 // #endregion 4879 // #region GRAPHICSTRING type 4880 case 25: 4881 new_asn1_type = in_window.org.pkijs.asn1.GRAPHICSTRING; 4882 break; 4883 // #endregion 4884 // #region VISIBLESTRING type 4885 case 26: 4886 new_asn1_type = in_window.org.pkijs.asn1.VISIBLESTRING; 4887 break; 4888 // #endregion 4889 // #region GENERALSTRING type 4890 case 27: 4891 new_asn1_type = in_window.org.pkijs.asn1.GENERALSTRING; 4892 break; 4893 // #endregion 4894 // #region UNIVERSALSTRING type 4895 case 28: 4896 new_asn1_type = in_window.org.pkijs.asn1.UNIVERSALSTRING; 4897 break; 4898 // #endregion 4899 // #region CHARACTERSTRING type 4900 case 29: 4901 new_asn1_type = in_window.org.pkijs.asn1.CHARACTERSTRING; 4902 break; 4903 // #endregion 4904 // #region BMPSTRING type 4905 case 30: 4906 new_asn1_type = in_window.org.pkijs.asn1.BMPSTRING; 4907 break; 4908 // #endregion 4909 // #region DATE type 4910 case 31: 4911 new_asn1_type = in_window.org.pkijs.asn1.DATE; 4912 break; 4913 // #endregion 4914 // #region TIMEOFDAY type 4915 case 32: 4916 new_asn1_type = in_window.org.pkijs.asn1.TIMEOFDAY; 4917 break; 4918 // #endregion 4919 // #region DATE-TIME type 4920 case 33: 4921 new_asn1_type = in_window.org.pkijs.asn1.DATETIME; 4922 break; 4923 // #endregion 4924 // #region DURATION type 4925 case 34: 4926 new_asn1_type = in_window.org.pkijs.asn1.DURATION; 4927 break; 4928 // #endregion 4929 // #region default 4930 default: 4931 { 4932 var new_object; 4933 4934 if(return_object.id_block.is_constructed == true) 4935 new_object = new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED(); 4936 else 4937 new_object = new in_window.org.pkijs.asn1.ASN1_PRIMITIVE(); 4938 4939 new_object.id_block = return_object.id_block; 4940 new_object.len_block = return_object.len_block; 4941 new_object.warnings = return_object.warnings; 4942 4943 return_object = new_object; 4944 4945 result_offset = return_object.fromBER(input_buffer, input_offset, input_length); 4946 } 4947 // #endregion 4948 } 4949 break; 4950 // #endregion 4951 // #region All other tag classes 4952 case 2: // APPLICATION 4953 case 3: // CONTEXT-SPECIFIC 4954 case 4: // PRIVATE 4955 default: 4956 { 4957 if(return_object.id_block.is_constructed == true) 4958 new_asn1_type = in_window.org.pkijs.asn1.ASN1_CONSTRUCTED; 4959 else 4960 new_asn1_type = in_window.org.pkijs.asn1.ASN1_PRIMITIVE; 4961 } 4962 // #endregion 4963 } 4964 // #endregion 4965 4966 // #region Change type and perform BER decoding 4967 return_object = local_change_type(return_object, new_asn1_type); 4968 result_offset = return_object.fromBER(input_buffer, input_offset, (return_object.len_block.is_indefinite_form == true) ? input_length : return_object.len_block.length); 4969 // #endregion 4970 4971 // #region Coping incoming buffer for entire ASN.1 block 4972 return_object.value_before_decode = util_copybuf_offset(input_buffer, incoming_offset, return_object.block_length); 4973 // #endregion 4974 4975 return { 4976 offset: result_offset, 4977 result: return_object 4978 }; 4979 } 4980 //************************************************************************************** 4981 in_window.org.pkijs.fromBER = 4982 function(input_buffer) 4983 { 4984 /// <summary>Major function for decoding ASN.1 BER array into internal library structuries</summary> 4985 /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array of bytes</param> 4986 4987 if(input_buffer.byteLength == 0) 4988 { 4989 var result = new in_window.org.pkijs.asn1.ASN1_block(); 4990 result.error = "Input buffer has zero length"; 4991 4992 return { 4993 offset: (-1), 4994 result: result 4995 }; 4996 } 4997 4998 return fromBER_raw(input_buffer, 0, input_buffer.byteLength); 4999 }; 5000 //************************************************************************************** 5001 // #endregion 5002 //************************************************************************************** 5003 // #region Major scheme verification function 5004 //************************************************************************************** 5005 in_window.org.pkijs.compareSchema = 5006 function(root, input_asn1_data, input_asn1_schema) 5007 { 5008 // #region Special case for CHOICE schema element type 5009 if(input_asn1_schema instanceof in_window.org.pkijs.asn1.CHOICE) 5010 { 5011 var choice_result = false; 5012 5013 for(var j = 0; j < input_asn1_schema.value.length; j++) 5014 { 5015 var result = in_window.org.pkijs.compareSchema(root, input_asn1_data, input_asn1_schema.value[j]); 5016 if(result.verified === true) 5017 return { 5018 verified: true, 5019 result: root 5020 }; 5021 } 5022 5023 if(choice_result === false) 5024 { 5025 var _result = { 5026 verified: false, 5027 result: { 5028 error: "Wrong values for CHOICE type" 5029 } 5030 }; 5031 5032 if(input_asn1_schema.hasOwnProperty('name')) 5033 _result.name = input_asn1_schema.name; 5034 5035 return _result; 5036 } 5037 } 5038 // #endregion 5039 5040 // #region Special case for ANY schema element type 5041 if(input_asn1_schema instanceof in_window.org.pkijs.asn1.ANY) 5042 { 5043 // #region Add named component of ASN.1 schema 5044 if(input_asn1_schema.hasOwnProperty('name')) 5045 root[input_asn1_schema.name] = input_asn1_data; 5046 // #endregion 5047 5048 return { 5049 verified: true, 5050 result: root 5051 }; 5052 } 5053 // #endregion 5054 5055 // #region Initial check 5056 if((root instanceof Object) === false) 5057 return { 5058 verified: false, 5059 result: { error: "Wrong root object" } 5060 }; 5061 5062 if((input_asn1_data instanceof Object) === false) 5063 return { 5064 verified: false, 5065 result: { error: "Wrong ASN.1 data" } 5066 }; 5067 5068 if((input_asn1_schema instanceof Object) === false) 5069 return { 5070 verified: false, 5071 result: { error: "Wrong ASN.1 schema" } 5072 }; 5073 5074 if(('id_block' in input_asn1_schema) === false) 5075 return { 5076 verified: false, 5077 result: { error: "Wrong ASN.1 schema" } 5078 }; 5079 // #endregion 5080 5081 // #region Comparing id_block properties in ASN.1 data and ASN.1 schema 5082 // #region Encode and decode ASN.1 schema id_block 5083 /// <remarks>This encoding/decoding is neccessary because could be an errors in schema definition</remarks> 5084 if(('fromBER' in input_asn1_schema.id_block) === false) 5085 return { 5086 verified: false, 5087 result: { error: "Wrong ASN.1 schema" } 5088 }; 5089 5090 if(('toBER' in input_asn1_schema.id_block) === false) 5091 return { 5092 verified: false, 5093 result: { error: "Wrong ASN.1 schema" } 5094 }; 5095 5096 var encoded_id = input_asn1_schema.id_block.toBER(false); 5097 if(encoded_id.byteLength === 0) 5098 return { 5099 verified: false, 5100 result: { error: "Error encoding id_block for ASN.1 schema" } 5101 }; 5102 5103 var decoded_offset = input_asn1_schema.id_block.fromBER(encoded_id, 0, encoded_id.byteLength); 5104 if(decoded_offset === (-1)) 5105 return { 5106 verified: false, 5107 result: { error: "Error decoding id_block for ASN.1 schema" } 5108 }; 5109 // #endregion 5110 5111 // #region tag_class 5112 if(input_asn1_schema.id_block.hasOwnProperty('tag_class') === false) 5113 return { 5114 verified: false, 5115 result: { error: "Wrong ASN.1 schema" } 5116 }; 5117 5118 if(input_asn1_schema.id_block.tag_class !== input_asn1_data.id_block.tag_class) 5119 return { 5120 verified: false, 5121 result: root 5122 }; 5123 // #endregion 5124 // #region tag_number 5125 if(input_asn1_schema.id_block.hasOwnProperty('tag_number') === false) 5126 return { 5127 verified: false, 5128 result: { error: "Wrong ASN.1 schema" } 5129 }; 5130 5131 if(input_asn1_schema.id_block.tag_number !== input_asn1_data.id_block.tag_number) 5132 return { 5133 verified: false, 5134 result: root 5135 }; 5136 // #endregion 5137 // #region is_constructed 5138 if(input_asn1_schema.id_block.hasOwnProperty('is_constructed') === false) 5139 return { 5140 verified: false, 5141 result: { error: "Wrong ASN.1 schema" } 5142 }; 5143 5144 if(input_asn1_schema.id_block.is_constructed !== input_asn1_data.id_block.is_constructed) 5145 return { 5146 verified: false, 5147 result: root 5148 }; 5149 // #endregion 5150 // #region is_hex_only 5151 if(('is_hex_only' in input_asn1_schema.id_block) === false) // Since 'is_hex_only' is an inhirited property 5152 return { 5153 verified: false, 5154 result: { error: "Wrong ASN.1 schema" } 5155 }; 5156 5157 if(input_asn1_schema.id_block.is_hex_only !== input_asn1_data.id_block.is_hex_only) 5158 return { 5159 verified: false, 5160 result: root 5161 }; 5162 // #endregion 5163 // #region value_hex 5164 if(input_asn1_schema.id_block.is_hex_only === true) 5165 { 5166 if(('value_hex' in input_asn1_schema.id_block) === false) // Since 'value_hex' is an inhirited property 5167 return { 5168 verified: false, 5169 result: { error: "Wrong ASN.1 schema" } 5170 }; 5171 5172 var schema_view = new Uint8Array(input_asn1_schema.id_block.value_hex); 5173 var asn1_view = new Uint8Array(input_asn1_data.id_block.value_hex); 5174 5175 if(schema_view.length !== asn1_view.length) 5176 return { 5177 verified: false, 5178 result: root 5179 }; 5180 5181 for(var i = 0; i < schema_view.length; i++) 5182 { 5183 if(schema_view[i] !== asn1_view[1]) 5184 return { 5185 verified: false, 5186 result: root 5187 }; 5188 } 5189 } 5190 // #endregion 5191 // #endregion 5192 5193 // #region Add named component of ASN.1 schema 5194 if(input_asn1_schema.hasOwnProperty('name')) 5195 { 5196 input_asn1_schema.name = input_asn1_schema.name.replace(/^\s+|\s+$/g, ''); 5197 if(input_asn1_schema.name !== "") 5198 root[input_asn1_schema.name] = input_asn1_data; 5199 } 5200 // #endregion 5201 5202 // #region Getting next ASN.1 block for comparition 5203 if(input_asn1_schema.id_block.is_constructed === true) 5204 { 5205 var admission = 0; 5206 var result = { verified: false }; 5207 5208 var max_length = input_asn1_schema.value_block.value.length; 5209 5210 if(max_length > 0) 5211 { 5212 if(input_asn1_schema.value_block.value[0] instanceof in_window.org.pkijs.asn1.REPEATED) 5213 max_length = input_asn1_data.value_block.value.length; 5214 } 5215 5216 // #region Special case when constructive value has no elements 5217 if(max_length === 0) 5218 return { 5219 verified: true, 5220 result: root 5221 }; 5222 // #endregion 5223 5224 // #region Special case when "input_asn1_data" has no values and "input_asn1_schema" has all optional values 5225 if((input_asn1_data.value_block.value.length === 0) && 5226 (input_asn1_schema.value_block.value.length !== 0)) 5227 { 5228 var _optional = true; 5229 5230 for(var i = 0; i < input_asn1_schema.value_block.value.length; i++) 5231 _optional = _optional && (input_asn1_schema.value_block.value[i].optional || false); 5232 5233 if(_optional === true) 5234 { 5235 return { 5236 verified: true, 5237 result: root 5238 }; 5239 } 5240 else 5241 { 5242 // #region Delete early added name of block 5243 if(input_asn1_schema.hasOwnProperty('name')) 5244 { 5245 input_asn1_schema.name = input_asn1_schema.name.replace(/^\s+|\s+$/g, ''); 5246 if(input_asn1_schema.name !== "") 5247 delete root[input_asn1_schema.name]; 5248 } 5249 // #endregion 5250 5251 root.error = "Inconsistent object length"; 5252 5253 return { 5254 verified: false, 5255 result: root 5256 }; 5257 } 5258 } 5259 // #endregion 5260 5261 for(var i = 0; i < max_length; i++) 5262 { 5263 // #region Special case when there is an "optional" element of ASN.1 schema at the end 5264 if((i - admission) >= input_asn1_data.value_block.value.length) 5265 { 5266 if(input_asn1_schema.value_block.value[i].optional === false) 5267 { 5268 var _result = { 5269 verified: false, 5270 result: root 5271 }; 5272 5273 root.error = "Inconsistent length between ASN.1 data and schema"; 5274 5275 // #region Delete early added name of block 5276 if(input_asn1_schema.hasOwnProperty('name')) 5277 { 5278 input_asn1_schema.name = input_asn1_schema.name.replace(/^\s+|\s+$/g, ''); 5279 if(input_asn1_schema.name !== "") 5280 { 5281 delete root[input_asn1_schema.name]; 5282 _result.name = input_asn1_schema.name; 5283 } 5284 } 5285 // #endregion 5286 5287 return _result; 5288 } 5289 } 5290 // #endregion 5291 else 5292 { 5293 // #region Special case for REPEATED type of ASN.1 schema element 5294 if(input_asn1_schema.value_block.value[0] instanceof in_window.org.pkijs.asn1.REPEATED) 5295 { 5296 result = in_window.org.pkijs.compareSchema(root, input_asn1_data.value_block.value[i], input_asn1_schema.value_block.value[0].value); 5297 if(result.verified === false) 5298 { 5299 if(input_asn1_schema.value_block.value[0].optional === true) 5300 admission++; 5301 else 5302 { 5303 // #region Delete early added name of block 5304 if(input_asn1_schema.hasOwnProperty('name')) 5305 { 5306 input_asn1_schema.name = input_asn1_schema.name.replace(/^\s+|\s+$/g, ''); 5307 if(input_asn1_schema.name !== "") 5308 delete root[input_asn1_schema.name]; 5309 } 5310 // #endregion 5311 5312 return result; 5313 } 5314 } 5315 5316 if(("name" in input_asn1_schema.value_block.value[0]) && (input_asn1_schema.value_block.value[0].name.length > 0)) 5317 { 5318 var array_root = {}; 5319 5320 if(("local" in input_asn1_schema.value_block.value[0]) && (input_asn1_schema.value_block.value[0].local === true)) 5321 array_root = input_asn1_data; 5322 else 5323 array_root = root; 5324 5325 if(typeof array_root[input_asn1_schema.value_block.value[0].name] === "undefined") 5326 array_root[input_asn1_schema.value_block.value[0].name] = new Array(); 5327 5328 array_root[input_asn1_schema.value_block.value[0].name].push(input_asn1_data.value_block.value[i]); 5329 } 5330 } 5331 // #endregion 5332 else 5333 { 5334 result = in_window.org.pkijs.compareSchema(root, input_asn1_data.value_block.value[i - admission], input_asn1_schema.value_block.value[i]); 5335 if(result.verified === false) 5336 { 5337 if(input_asn1_schema.value_block.value[i].optional === true) 5338 admission++; 5339 else 5340 { 5341 // #region Delete early added name of block 5342 if(input_asn1_schema.hasOwnProperty('name')) 5343 { 5344 input_asn1_schema.name = input_asn1_schema.name.replace(/^\s+|\s+$/g, ''); 5345 if(input_asn1_schema.name !== "") 5346 delete root[input_asn1_schema.name]; 5347 } 5348 // #endregion 5349 5350 return result; 5351 } 5352 } 5353 } 5354 } 5355 } 5356 5357 if(result.verified === false) // The situation may take place if last element is "optional" and verification failed 5358 { 5359 var _result = { 5360 verified: false, 5361 result: root 5362 }; 5363 5364 // #region Delete early added name of block 5365 if(input_asn1_schema.hasOwnProperty('name')) 5366 { 5367 input_asn1_schema.name = input_asn1_schema.name.replace(/^\s+|\s+$/g, ''); 5368 if(input_asn1_schema.name !== "") 5369 { 5370 delete root[input_asn1_schema.name]; 5371 _result.name = input_asn1_schema.name; 5372 } 5373 } 5374 // #endregion 5375 5376 return _result; 5377 } 5378 5379 return { 5380 verified: true, 5381 result: root 5382 }; 5383 } 5384 // #endregion 5385 // #region Ability to parse internal value for primitive-encoded value (value of OCTETSTRING, for example) 5386 else 5387 { 5388 if( ("primitive_schema" in input_asn1_schema) && 5389 ("value_hex" in input_asn1_data.value_block) ) 5390 { 5391 // #region Decoding of raw ASN.1 data 5392 var asn1 = in_window.org.pkijs.fromBER(input_asn1_data.value_block.value_hex); 5393 if(asn1.offset === (-1)) 5394 { 5395 var _result = { 5396 verified: false, 5397 result: asn1.result 5398 }; 5399 5400 // #region Delete early added name of block 5401 if(input_asn1_schema.hasOwnProperty('name')) 5402 { 5403 input_asn1_schema.name = input_asn1_schema.name.replace(/^\s+|\s+$/g, ''); 5404 if(input_asn1_schema.name !== "") 5405 { 5406 delete root[input_asn1_schema.name]; 5407 _result.name = input_asn1_schema.name; 5408 } 5409 } 5410 // #endregion 5411 5412 return _result; 5413 } 5414 // #endregion 5415 5416 return in_window.org.pkijs.compareSchema(root, asn1.result, input_asn1_schema.primitive_schema); 5417 } 5418 else 5419 return { 5420 verified: true, 5421 result: root 5422 }; 5423 } 5424 // #endregion 5425 }; 5426 //************************************************************************************** 5427 in_window.org.pkijs.verifySchema = 5428 function(input_buffer, input_schema) 5429 { 5430 // #region Initial check 5431 if((input_schema instanceof Object) === false) 5432 return { 5433 verified: false, 5434 result: { error: "Wrong ASN.1 schema type" } 5435 }; 5436 // #endregion 5437 5438 // #region Decoding of raw ASN.1 data 5439 var asn1 = in_window.org.pkijs.fromBER(input_buffer); 5440 if(asn1.offset === (-1)) 5441 return { 5442 verified: false, 5443 result: asn1.result 5444 }; 5445 // #endregion 5446 5447 // #region Compare ASN.1 struct with input schema 5448 return in_window.org.pkijs.compareSchema(asn1.result, asn1.result, input_schema); 5449 // #endregion 5450 }; 5451 //************************************************************************************** 5452 // #endregion 5453 //************************************************************************************** 5454 // #region Major function converting JSON to ASN.1 objects 5455 //************************************************************************************** 5456 in_window.org.pkijs.fromJSON = 5457 function(json) 5458 { 5459 /// <summary>Converting from JSON to ASN.1 objects</summary> 5460 /// <param name="json" type="String|Object">JSON string or object to convert to ASN.1 objects</param> 5461 }; 5462 //************************************************************************************** 5463 // #endregion 5464 //************************************************************************************** 5465 } 5466 )(typeof exports !== "undefined" ? exports : window);