001/* 002 * Copyright 2009-2020 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright 2009-2020 Ping Identity Corporation 007 * 008 * Licensed under the Apache License, Version 2.0 (the "License"); 009 * you may not use this file except in compliance with the License. 010 * You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, software 015 * distributed under the License is distributed on an "AS IS" BASIS, 016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 017 * See the License for the specific language governing permissions and 018 * limitations under the License. 019 */ 020/* 021 * Copyright (C) 2009-2020 Ping Identity Corporation 022 * 023 * This program is free software; you can redistribute it and/or modify 024 * it under the terms of the GNU General Public License (GPLv2 only) 025 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 026 * as published by the Free Software Foundation. 027 * 028 * This program is distributed in the hope that it will be useful, 029 * but WITHOUT ANY WARRANTY; without even the implied warranty of 030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 031 * GNU General Public License for more details. 032 * 033 * You should have received a copy of the GNU General Public License 034 * along with this program; if not, see <http://www.gnu.org/licenses>. 035 */ 036package com.unboundid.asn1; 037 038 039 040import java.io.IOException; 041import java.io.OutputStream; 042import java.io.Serializable; 043import java.math.BigInteger; 044import java.nio.ByteBuffer; 045import java.util.Date; 046import java.util.concurrent.atomic.AtomicBoolean; 047 048import com.unboundid.util.ByteStringBuffer; 049import com.unboundid.util.Debug; 050import com.unboundid.util.DebugType; 051import com.unboundid.util.Mutable; 052import com.unboundid.util.ThreadSafety; 053import com.unboundid.util.ThreadSafetyLevel; 054 055 056 057/** 058 * This class provides a mechanism for writing one or more ASN.1 elements into a 059 * byte string buffer. It may be cleared and re-used any number of times, and 060 * the contents may be written to an {@code OutputStream} or {@code ByteBuffer}, 061 * or copied to a byte array. {@code ASN1Buffer} instances are not threadsafe 062 * and should not be accessed concurrently by multiple threads. 063 */ 064@Mutable() 065@ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE) 066public final class ASN1Buffer 067 implements Serializable 068{ 069 /** 070 * The default maximum buffer size. 071 */ 072 private static final int DEFAULT_MAX_BUFFER_SIZE = 1_048_576; 073 074 075 076 /** 077 * An array that will be inserted when completing a sequence whose 078 * multi-byte length should be encoded with one byte for the header and one 079 * byte for the number of value bytes. 080 */ 081 private static final byte[] MULTIBYTE_LENGTH_HEADER_PLUS_ONE = 082 { (byte) 0x81, (byte) 0x00 }; 083 084 085 086 /** 087 * An array that will be inserted when completing a sequence whose 088 * multi-byte length should be encoded with one byte for the header and two 089 * bytes for the number of value bytes. 090 */ 091 private static final byte[] MULTIBYTE_LENGTH_HEADER_PLUS_TWO = 092 { (byte) 0x82, (byte) 0x00, (byte) 0x00 }; 093 094 095 096 /** 097 * An array that will be inserted when completing a sequence whose 098 * multi-byte length should be encoded with one byte for the header and three 099 * bytes for the number of value bytes. 100 */ 101 private static final byte[] MULTIBYTE_LENGTH_HEADER_PLUS_THREE = 102 { (byte) 0x83, (byte) 0x00, (byte) 0x00, (byte) 0x00 }; 103 104 105 106 /** 107 * An array that will be inserted when completing a sequence whose 108 * multi-byte length should be encoded with one byte for the header and four 109 * bytes for the number of value bytes. 110 */ 111 private static final byte[] MULTIBYTE_LENGTH_HEADER_PLUS_FOUR = 112 { (byte) 0x84, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 }; 113 114 115 116 /** 117 * The serial version UID for this serializable class. 118 */ 119 private static final long serialVersionUID = -4898230771376551562L; 120 121 122 123 // Indicates whether to zero out the contents of the buffer the next time it 124 // is cleared in order to wipe out any sensitive data it may contain. 125 private final AtomicBoolean zeroBufferOnClear; 126 127 // The buffer to which all data will be written. 128 private final ByteStringBuffer buffer; 129 130 // The maximum buffer size that should be retained. 131 private final int maxBufferSize; 132 133 134 135 /** 136 * Creates a new instance of this ASN.1 buffer. 137 */ 138 public ASN1Buffer() 139 { 140 this(DEFAULT_MAX_BUFFER_SIZE); 141 } 142 143 144 145 /** 146 * Creates a new instance of this ASN.1 buffer with an optional maximum 147 * retained size. If a maximum size is defined, then this buffer may be used 148 * to hold elements larger than that, but when the buffer is cleared it will 149 * be shrunk to the maximum size. 150 * 151 * @param maxBufferSize The maximum buffer size that will be retained by 152 * this ASN.1 buffer. A value less than or equal to 153 * zero indicates that no maximum size should be 154 * enforced. 155 */ 156 public ASN1Buffer(final int maxBufferSize) 157 { 158 this.maxBufferSize = maxBufferSize; 159 160 buffer = new ByteStringBuffer(); 161 zeroBufferOnClear = new AtomicBoolean(false); 162 } 163 164 165 166 /** 167 * Indicates whether the content of the buffer should be zeroed out the next 168 * time it is cleared in order to wipe any sensitive information it may 169 * contain. 170 * 171 * @return {@code true} if the content of the buffer should be zeroed out the 172 * next time it is cleared, or {@code false} if not. 173 */ 174 public boolean zeroBufferOnClear() 175 { 176 return zeroBufferOnClear.get(); 177 } 178 179 180 181 /** 182 * Specifies that the content of the buffer should be zeroed out the next time 183 * it is cleared in order to wipe any sensitive information it may contain. 184 */ 185 public void setZeroBufferOnClear() 186 { 187 zeroBufferOnClear.set(true); 188 } 189 190 191 192 /** 193 * Clears the contents of this buffer. If there are any outstanding sequences 194 * or sets that have been created but not closed, then they must no longer be 195 * used and any attempt to do so may yield unpredictable results. 196 */ 197 public void clear() 198 { 199 buffer.clear(zeroBufferOnClear.getAndSet(false)); 200 201 if ((maxBufferSize > 0) && (buffer.capacity() > maxBufferSize)) 202 { 203 buffer.setCapacity(maxBufferSize); 204 } 205 } 206 207 208 209 /** 210 * Retrieves the current length of this buffer in bytes. 211 * 212 * @return The current length of this buffer in bytes. 213 */ 214 public int length() 215 { 216 return buffer.length(); 217 } 218 219 220 221 /** 222 * Adds the provided ASN.1 element to this ASN.1 buffer. 223 * 224 * @param element The element to be added. It must not be {@code null}. 225 */ 226 public void addElement(final ASN1Element element) 227 { 228 element.encodeTo(buffer); 229 } 230 231 232 233 /** 234 * Adds a Boolean element to this ASN.1 buffer using the default BER type. 235 * 236 * @param booleanValue The value to use for the Boolean element. 237 */ 238 public void addBoolean(final boolean booleanValue) 239 { 240 addBoolean(ASN1Constants.UNIVERSAL_BOOLEAN_TYPE, booleanValue); 241 } 242 243 244 245 /** 246 * Adds a Boolean element to this ASN.1 buffer using the provided BER type. 247 * 248 * @param type The BER type to use for the Boolean element. 249 * @param booleanValue The value to use for the Boolean element. 250 */ 251 public void addBoolean(final byte type, final boolean booleanValue) 252 { 253 buffer.append(type); 254 buffer.append((byte) 0x01); 255 256 if (booleanValue) 257 { 258 buffer.append((byte) 0xFF); 259 } 260 else 261 { 262 buffer.append((byte) 0x00); 263 } 264 } 265 266 267 268 /** 269 * Adds an enumerated element to this ASN.1 buffer using the default BER type. 270 * 271 * @param intValue The value to use for the enumerated element. 272 */ 273 public void addEnumerated(final int intValue) 274 { 275 addInteger(ASN1Constants.UNIVERSAL_ENUMERATED_TYPE, intValue); 276 } 277 278 279 280 /** 281 * Adds an enumerated element to this ASN.1 buffer using the provided BER 282 * type. 283 * 284 * @param type The BER type to use for the enumerated element. 285 * @param intValue The value to use for the enumerated element. 286 */ 287 public void addEnumerated(final byte type, final int intValue) 288 { 289 addInteger(type, intValue); 290 } 291 292 293 294 /** 295 * Adds a generalized time element to this ASN.1 buffer using the default BER 296 * type. 297 * 298 * @param date The date value that specifies the time to represent. This 299 * must not be {@code null}. 300 */ 301 public void addGeneralizedTime(final Date date) 302 { 303 addGeneralizedTime(date.getTime()); 304 } 305 306 307 308 /** 309 * Adds a generalized time element to this ASN.1 buffer using the provided BER 310 * type. 311 * 312 * @param type The BER type to use for the generalized time element. 313 * @param date The date value that specifies the time to represent. This 314 * must not be {@code null}. 315 */ 316 public void addGeneralizedTime(final byte type, final Date date) 317 { 318 addGeneralizedTime(type, date.getTime()); 319 } 320 321 322 323 /** 324 * Adds a generalized time element to this ASN.1 buffer using the default BER 325 * type. 326 * 327 * @param time The time to represent. This must be expressed in 328 * milliseconds since the epoch (the same format used by 329 * {@code System.currentTimeMillis()} and 330 * {@code Date.getTime()}). 331 */ 332 public void addGeneralizedTime(final long time) 333 { 334 addGeneralizedTime(ASN1Constants.UNIVERSAL_GENERALIZED_TIME_TYPE, time); 335 } 336 337 338 339 /** 340 * Adds a generalized time element to this ASN.1 buffer using the provided BER 341 * type. 342 * 343 * @param type The BER type to use for the generalized time element. 344 * @param time The time to represent. This must be expressed in 345 * milliseconds since the epoch (the same format used by 346 * {@code System.currentTimeMillis()} and 347 * {@code Date.getTime()}). 348 */ 349 public void addGeneralizedTime(final byte type, final long time) 350 { 351 buffer.append(type); 352 353 final String timestamp = ASN1GeneralizedTime.encodeTimestamp(time, true); 354 ASN1Element.encodeLengthTo(timestamp.length(), buffer); 355 buffer.append(timestamp); 356 } 357 358 359 360 /** 361 * Adds an integer element to this ASN.1 buffer using the default BER type. 362 * 363 * @param intValue The value to use for the integer element. 364 */ 365 public void addInteger(final int intValue) 366 { 367 addInteger(ASN1Constants.UNIVERSAL_INTEGER_TYPE, intValue); 368 } 369 370 371 372 /** 373 * Adds an integer element to this ASN.1 buffer using the provided BER type. 374 * 375 * @param type The BER type to use for the integer element. 376 * @param intValue The value to use for the integer element. 377 */ 378 public void addInteger(final byte type, final int intValue) 379 { 380 buffer.append(type); 381 382 if (intValue < 0) 383 { 384 if ((intValue & 0xFFFF_FF80) == 0xFFFF_FF80) 385 { 386 buffer.append((byte) 0x01); 387 buffer.append((byte) (intValue & 0xFF)); 388 } 389 else if ((intValue & 0xFFFF_8000) == 0xFFFF_8000) 390 { 391 buffer.append((byte) 0x02); 392 buffer.append((byte) ((intValue >> 8) & 0xFF)); 393 buffer.append((byte) (intValue & 0xFF)); 394 } 395 else if ((intValue & 0xFF80_0000) == 0xFF80_0000) 396 { 397 buffer.append((byte) 0x03); 398 buffer.append((byte) ((intValue >> 16) & 0xFF)); 399 buffer.append((byte) ((intValue >> 8) & 0xFF)); 400 buffer.append((byte) (intValue & 0xFF)); 401 } 402 else 403 { 404 buffer.append((byte) 0x04); 405 buffer.append((byte) ((intValue >> 24) & 0xFF)); 406 buffer.append((byte) ((intValue >> 16) & 0xFF)); 407 buffer.append((byte) ((intValue >> 8) & 0xFF)); 408 buffer.append((byte) (intValue & 0xFF)); 409 } 410 } 411 else 412 { 413 if ((intValue & 0x0000_007F) == intValue) 414 { 415 buffer.append((byte) 0x01); 416 buffer.append((byte) (intValue & 0x7F)); 417 } 418 else if ((intValue & 0x0000_7FFF) == intValue) 419 { 420 buffer.append((byte) 0x02); 421 buffer.append((byte) ((intValue >> 8) & 0x7F)); 422 buffer.append((byte) (intValue & 0xFF)); 423 } 424 else if ((intValue & 0x007F_FFFF) == intValue) 425 { 426 buffer.append((byte) 0x03); 427 buffer.append((byte) ((intValue >> 16) & 0x7F)); 428 buffer.append((byte) ((intValue >> 8) & 0xFF)); 429 buffer.append((byte) (intValue & 0xFF)); 430 } 431 else 432 { 433 buffer.append((byte) 0x04); 434 buffer.append((byte) ((intValue >> 24) & 0x7F)); 435 buffer.append((byte) ((intValue >> 16) & 0xFF)); 436 buffer.append((byte) ((intValue >> 8) & 0xFF)); 437 buffer.append((byte) (intValue & 0xFF)); 438 } 439 } 440 } 441 442 443 444 /** 445 * Adds an integer element to this ASN.1 buffer using the default BER type. 446 * 447 * @param longValue The value to use for the integer element. 448 */ 449 public void addInteger(final long longValue) 450 { 451 addInteger(ASN1Constants.UNIVERSAL_INTEGER_TYPE, longValue); 452 } 453 454 455 456 /** 457 * Adds an integer element to this ASN.1 buffer using the provided BER type. 458 * 459 * @param type The BER type to use for the integer element. 460 * @param longValue The value to use for the integer element. 461 */ 462 public void addInteger(final byte type, final long longValue) 463 { 464 buffer.append(type); 465 466 if (longValue < 0) 467 { 468 if ((longValue & 0xFFFF_FFFF_FFFF_FF80L) == 0xFFFF_FFFF_FFFF_FF80L) 469 { 470 buffer.append((byte) 0x01); 471 buffer.append((byte) (longValue & 0xFFL)); 472 } 473 else if ((longValue & 0xFFFF_FFFF_FFFF_8000L) == 0xFFFF_FFFF_FFFF_8000L) 474 { 475 buffer.append((byte) 0x02); 476 buffer.append((byte) ((longValue >> 8) & 0xFFL)); 477 buffer.append((byte) (longValue & 0xFFL)); 478 } 479 else if ((longValue & 0xFFFF_FFFF_FF80_0000L) == 0xFFFF_FFFF_FF80_0000L) 480 { 481 buffer.append((byte) 0x03); 482 buffer.append((byte) ((longValue >> 16) & 0xFFL)); 483 buffer.append((byte) ((longValue >> 8) & 0xFFL)); 484 buffer.append((byte) (longValue & 0xFFL)); 485 } 486 else if ((longValue & 0xFFFF_FFFF_8000_0000L) == 0xFFFF_FFFF_8000_0000L) 487 { 488 buffer.append((byte) 0x04); 489 buffer.append((byte) ((longValue >> 24) & 0xFFL)); 490 buffer.append((byte) ((longValue >> 16) & 0xFFL)); 491 buffer.append((byte) ((longValue >> 8) & 0xFFL)); 492 buffer.append((byte) (longValue & 0xFFL)); 493 } 494 else if ((longValue & 0xFFFF_FF80_0000_0000L) == 0xFFFF_FF80_0000_0000L) 495 { 496 buffer.append((byte) 0x05); 497 buffer.append((byte) ((longValue >> 32) & 0xFFL)); 498 buffer.append((byte) ((longValue >> 24) & 0xFFL)); 499 buffer.append((byte) ((longValue >> 16) & 0xFFL)); 500 buffer.append((byte) ((longValue >> 8) & 0xFFL)); 501 buffer.append((byte) (longValue & 0xFFL)); 502 } 503 else if ((longValue & 0xFFFF_8000_0000_0000L) == 0xFFFF_8000_0000_0000L) 504 { 505 buffer.append((byte) 0x06); 506 buffer.append((byte) ((longValue >> 40) & 0xFFL)); 507 buffer.append((byte) ((longValue >> 32) & 0xFFL)); 508 buffer.append((byte) ((longValue >> 24) & 0xFFL)); 509 buffer.append((byte) ((longValue >> 16) & 0xFFL)); 510 buffer.append((byte) ((longValue >> 8) & 0xFFL)); 511 buffer.append((byte) (longValue & 0xFFL)); 512 } 513 else if ((longValue & 0xFF80_0000_0000_0000L) == 0xFF80_0000_0000_0000L) 514 { 515 buffer.append((byte) 0x07); 516 buffer.append((byte) ((longValue >> 48) & 0xFFL)); 517 buffer.append((byte) ((longValue >> 40) & 0xFFL)); 518 buffer.append((byte) ((longValue >> 32) & 0xFFL)); 519 buffer.append((byte) ((longValue >> 24) & 0xFFL)); 520 buffer.append((byte) ((longValue >> 16) & 0xFFL)); 521 buffer.append((byte) ((longValue >> 8) & 0xFFL)); 522 buffer.append((byte) (longValue & 0xFFL)); 523 } 524 else 525 { 526 buffer.append((byte) 0x08); 527 buffer.append((byte) ((longValue >> 56) & 0xFFL)); 528 buffer.append((byte) ((longValue >> 48) & 0xFFL)); 529 buffer.append((byte) ((longValue >> 40) & 0xFFL)); 530 buffer.append((byte) ((longValue >> 32) & 0xFFL)); 531 buffer.append((byte) ((longValue >> 24) & 0xFFL)); 532 buffer.append((byte) ((longValue >> 16) & 0xFFL)); 533 buffer.append((byte) ((longValue >> 8) & 0xFFL)); 534 buffer.append((byte) (longValue & 0xFFL)); 535 } 536 } 537 else 538 { 539 if ((longValue & 0x0000_0000_0000_007FL) == longValue) 540 { 541 buffer.append((byte) 0x01); 542 buffer.append((byte) (longValue & 0x7FL)); 543 } 544 else if ((longValue & 0x0000_0000_0000_7FFFL) == longValue) 545 { 546 buffer.append((byte) 0x02); 547 buffer.append((byte) ((longValue >> 8) & 0x7FL)); 548 buffer.append((byte) (longValue & 0xFFL)); 549 } 550 else if ((longValue & 0x0000_0000_007F_FFFFL) == longValue) 551 { 552 buffer.append((byte) 0x03); 553 buffer.append((byte) ((longValue >> 16) & 0x7FL)); 554 buffer.append((byte) ((longValue >> 8) & 0xFFL)); 555 buffer.append((byte) (longValue & 0xFFL)); 556 } 557 else if ((longValue & 0x0000_0000_7FFF_FFFFL) == longValue) 558 { 559 buffer.append((byte) 0x04); 560 buffer.append((byte) ((longValue >> 24) & 0x7FL)); 561 buffer.append((byte) ((longValue >> 16) & 0xFFL)); 562 buffer.append((byte) ((longValue >> 8) & 0xFFL)); 563 buffer.append((byte) (longValue & 0xFFL)); 564 } 565 else if ((longValue & 0x0000_007F_FFFF_FFFFL) == longValue) 566 { 567 buffer.append((byte) 0x05); 568 buffer.append((byte) ((longValue >> 32) & 0x7FL)); 569 buffer.append((byte) ((longValue >> 24) & 0xFFL)); 570 buffer.append((byte) ((longValue >> 16) & 0xFFL)); 571 buffer.append((byte) ((longValue >> 8) & 0xFFL)); 572 buffer.append((byte) (longValue & 0xFFL)); 573 } 574 else if ((longValue & 0x0000_7FFF_FFFF_FFFFL) == longValue) 575 { 576 buffer.append((byte) 0x06); 577 buffer.append((byte) ((longValue >> 40) & 0x7FL)); 578 buffer.append((byte) ((longValue >> 32) & 0xFFL)); 579 buffer.append((byte) ((longValue >> 24) & 0xFFL)); 580 buffer.append((byte) ((longValue >> 16) & 0xFFL)); 581 buffer.append((byte) ((longValue >> 8) & 0xFFL)); 582 buffer.append((byte) (longValue & 0xFFL)); 583 } 584 else if ((longValue & 0x007F_FFFF_FFFF_FFFFL) == longValue) 585 { 586 buffer.append((byte) 0x07); 587 buffer.append((byte) ((longValue >> 48) & 0x7FL)); 588 buffer.append((byte) ((longValue >> 40) & 0xFFL)); 589 buffer.append((byte) ((longValue >> 32) & 0xFFL)); 590 buffer.append((byte) ((longValue >> 24) & 0xFFL)); 591 buffer.append((byte) ((longValue >> 16) & 0xFFL)); 592 buffer.append((byte) ((longValue >> 8) & 0xFFL)); 593 buffer.append((byte) (longValue & 0xFFL)); 594 } 595 else 596 { 597 buffer.append((byte) 0x08); 598 buffer.append((byte) ((longValue >> 56) & 0x7FL)); 599 buffer.append((byte) ((longValue >> 48) & 0xFFL)); 600 buffer.append((byte) ((longValue >> 40) & 0xFFL)); 601 buffer.append((byte) ((longValue >> 32) & 0xFFL)); 602 buffer.append((byte) ((longValue >> 24) & 0xFFL)); 603 buffer.append((byte) ((longValue >> 16) & 0xFFL)); 604 buffer.append((byte) ((longValue >> 8) & 0xFFL)); 605 buffer.append((byte) (longValue & 0xFFL)); 606 } 607 } 608 } 609 610 611 612 /** 613 * Adds an integer element to this ASN.1 buffer using the default BER type. 614 * 615 * @param value The value to use for the integer element. It must not be 616 * {@code null}. 617 */ 618 public void addInteger(final BigInteger value) 619 { 620 addInteger(ASN1Constants.UNIVERSAL_INTEGER_TYPE, value); 621 } 622 623 624 625 /** 626 * Adds an integer element to this ASN.1 buffer using the provided BER type. 627 * 628 * @param type The BER type to use for the integer element. 629 * @param value The value to use for the integer element. It must not be 630 * {@code null}. 631 */ 632 public void addInteger(final byte type, final BigInteger value) 633 { 634 buffer.append(type); 635 636 final byte[] valueBytes = value.toByteArray(); 637 ASN1Element.encodeLengthTo(valueBytes.length, buffer); 638 buffer.append(valueBytes); 639 } 640 641 642 643 /** 644 * Adds a null element to this ASN.1 buffer using the default BER type. 645 */ 646 public void addNull() 647 { 648 addNull(ASN1Constants.UNIVERSAL_NULL_TYPE); 649 } 650 651 652 653 /** 654 * Adds a null element to this ASN.1 buffer using the provided BER type. 655 * 656 * @param type The BER type to use for the null element. 657 */ 658 public void addNull(final byte type) 659 { 660 buffer.append(type); 661 buffer.append((byte) 0x00); 662 } 663 664 665 666 /** 667 * Adds an octet string element to this ASN.1 buffer using the default BER 668 * type and no value. 669 */ 670 public void addOctetString() 671 { 672 addOctetString(ASN1Constants.UNIVERSAL_OCTET_STRING_TYPE); 673 } 674 675 676 677 /** 678 * Adds an octet string element to this ASN.1 buffer using the provided BER 679 * type and no value. 680 * 681 * @param type The BER type to use for the octet string element. 682 */ 683 public void addOctetString(final byte type) 684 { 685 buffer.append(type); 686 buffer.append((byte) 0x00); 687 } 688 689 690 691 /** 692 * Adds an octet string element to this ASN.1 buffer using the default BER 693 * type. 694 * 695 * @param value The value to use for the octet string element. 696 */ 697 public void addOctetString(final byte[] value) 698 { 699 addOctetString(ASN1Constants.UNIVERSAL_OCTET_STRING_TYPE, value); 700 } 701 702 703 704 /** 705 * Adds an octet string element to this ASN.1 buffer using the default BER 706 * type. 707 * 708 * @param value The value to use for the octet string element. 709 */ 710 public void addOctetString(final CharSequence value) 711 { 712 if (value == null) 713 { 714 addOctetString(ASN1Constants.UNIVERSAL_OCTET_STRING_TYPE); 715 } 716 else 717 { 718 addOctetString(ASN1Constants.UNIVERSAL_OCTET_STRING_TYPE, 719 value.toString()); 720 } 721 } 722 723 724 725 /** 726 * Adds an octet string element to this ASN.1 buffer using the default BER 727 * type. 728 * 729 * @param value The value to use for the octet string element. 730 */ 731 public void addOctetString(final String value) 732 { 733 addOctetString(ASN1Constants.UNIVERSAL_OCTET_STRING_TYPE, value); 734 } 735 736 737 738 /** 739 * Adds an octet string element to this ASN.1 buffer using the provided BER 740 * type. 741 * 742 * @param type The BER type to use for the octet string element. 743 * @param value The value to use for the octet string element. 744 */ 745 public void addOctetString(final byte type, final byte[] value) 746 { 747 buffer.append(type); 748 749 if (value == null) 750 { 751 buffer.append((byte) 0x00); 752 } 753 else 754 { 755 ASN1Element.encodeLengthTo(value.length, buffer); 756 buffer.append(value); 757 } 758 } 759 760 761 762 /** 763 * Adds an octet string element to this ASN.1 buffer using the provided BER 764 * type. 765 * 766 * @param type The BER type to use for the octet string element. 767 * @param value The value to use for the octet string element. 768 */ 769 public void addOctetString(final byte type, final CharSequence value) 770 { 771 if (value == null) 772 { 773 addOctetString(type); 774 } 775 else 776 { 777 addOctetString(type, value.toString()); 778 } 779 } 780 781 782 783 /** 784 * Adds an octet string element to this ASN.1 buffer using the provided BER 785 * type. 786 * 787 * @param type The BER type to use for the octet string element. 788 * @param value The value to use for the octet string element. 789 */ 790 public void addOctetString(final byte type, final String value) 791 { 792 buffer.append(type); 793 794 if (value == null) 795 { 796 buffer.append((byte) 0x00); 797 } 798 else 799 { 800 // We'll assume that the string contains only ASCII characters and 801 // therefore the number of bytes will equal the number of characters. 802 // However, save the position in case we're wrong and need to re-encode. 803 final int lengthStartPos = buffer.length(); 804 ASN1Element.encodeLengthTo(value.length(), buffer); 805 806 final int valueStartPos = buffer.length(); 807 buffer.append(value); 808 809 if (buffer.length() != (valueStartPos + value.length())) 810 { 811 final byte[] valueBytes = new byte[buffer.length() - valueStartPos]; 812 System.arraycopy(buffer.getBackingArray(), valueStartPos, valueBytes, 0, 813 valueBytes.length); 814 815 buffer.setLength(lengthStartPos); 816 ASN1Element.encodeLengthTo(valueBytes.length, buffer); 817 buffer.append(valueBytes); 818 } 819 } 820 } 821 822 823 824 /** 825 * Adds a UTC time element to this ASN.1 buffer using the default BER type. 826 * 827 * @param date The date value that specifies the time to represent. This 828 * must not be {@code null}. 829 */ 830 public void addUTCTime(final Date date) 831 { 832 addUTCTime(date.getTime()); 833 } 834 835 836 837 /** 838 * Adds a UTC time element to this ASN.1 buffer using the provided BER type. 839 * 840 * @param type The BER type to use for the UTC time element. 841 * @param date The date value that specifies the time to represent. This 842 * must not be {@code null}. 843 */ 844 public void addUTCTime(final byte type, final Date date) 845 { 846 addUTCTime(type, date.getTime()); 847 } 848 849 850 851 /** 852 * Adds a UTC time element to this ASN.1 buffer using the default BER type. 853 * 854 * @param time The time to represent. This must be expressed in 855 * milliseconds since the epoch (the same format used by 856 * {@code System.currentTimeMillis()} and 857 * {@code Date.getTime()}). 858 */ 859 public void addUTCTime(final long time) 860 { 861 addUTCTime(ASN1Constants.UNIVERSAL_UTC_TIME_TYPE, time); 862 } 863 864 865 866 /** 867 * Adds a UTC time element to this ASN.1 buffer using the provided BER type. 868 * 869 * @param type The BER type to use for the UTC time element. 870 * @param time The time to represent. This must be expressed in 871 * milliseconds since the epoch (the same format used by 872 * {@code System.currentTimeMillis()} and 873 * {@code Date.getTime()}). 874 */ 875 public void addUTCTime(final byte type, final long time) 876 { 877 buffer.append(type); 878 879 final String timestamp = ASN1UTCTime.encodeTimestamp(time); 880 ASN1Element.encodeLengthTo(timestamp.length(), buffer); 881 buffer.append(timestamp); 882 } 883 884 885 886 /** 887 * Begins adding elements to an ASN.1 sequence using the default BER type. 888 * 889 * @return An object that may be used to indicate when the end of the 890 * sequence has been reached. Once all embedded sequence elements 891 * have been added, then the {@link ASN1BufferSequence#end} method 892 * MUST be called to ensure that the sequence is properly encoded. 893 */ 894 public ASN1BufferSequence beginSequence() 895 { 896 return beginSequence(ASN1Constants.UNIVERSAL_SEQUENCE_TYPE); 897 } 898 899 900 901 /** 902 * Begins adding elements to an ASN.1 sequence using the provided BER type. 903 * 904 * @param type The BER type to use for the sequence. 905 * 906 * @return An object that may be used to indicate when the end of the 907 * sequence has been reached. Once all embedded sequence elements 908 * have been added, then the {@link ASN1BufferSequence#end} method 909 * MUST be called to ensure that the sequence is properly encoded. 910 */ 911 public ASN1BufferSequence beginSequence(final byte type) 912 { 913 buffer.append(type); 914 return new ASN1BufferSequence(this); 915 } 916 917 918 919 /** 920 * Begins adding elements to an ASN.1 set using the default BER type. 921 * 922 * @return An object that may be used to indicate when the end of the set has 923 * been reached. Once all embedded set elements have been added, 924 * then the {@link ASN1BufferSet#end} method MUST be called to ensure 925 * that the set is properly encoded. 926 */ 927 public ASN1BufferSet beginSet() 928 { 929 return beginSet(ASN1Constants.UNIVERSAL_SET_TYPE); 930 } 931 932 933 934 /** 935 * Begins adding elements to an ASN.1 set using the provided BER type. 936 * 937 * @param type The BER type to use for the set. 938 * 939 * @return An object that may be used to indicate when the end of the set has 940 * been reached. Once all embedded set elements have been added, 941 * then the {@link ASN1BufferSet#end} method MUST be called to ensure 942 * that the set is properly encoded. 943 */ 944 public ASN1BufferSet beginSet(final byte type) 945 { 946 buffer.append(type); 947 return new ASN1BufferSet(this); 948 } 949 950 951 952 /** 953 * Ensures that the appropriate length is inserted into the internal buffer 954 * after all elements in a sequence or set have been added. 955 * 956 * @param valueStartPos The position in which the first value was added. 957 */ 958 void endSequenceOrSet(final int valueStartPos) 959 { 960 final int length = buffer.length() - valueStartPos; 961 if (length == 0) 962 { 963 buffer.append((byte) 0x00); 964 return; 965 } 966 967 if ((length & 0x7F) == length) 968 { 969 buffer.insert(valueStartPos, (byte) length); 970 } 971 else if ((length & 0xFF) == length) 972 { 973 buffer.insert(valueStartPos, MULTIBYTE_LENGTH_HEADER_PLUS_ONE); 974 975 final byte[] backingArray = buffer.getBackingArray(); 976 backingArray[valueStartPos+1] = (byte) (length & 0xFF); 977 } 978 else if ((length & 0xFFFF) == length) 979 { 980 buffer.insert(valueStartPos, MULTIBYTE_LENGTH_HEADER_PLUS_TWO); 981 982 final byte[] backingArray = buffer.getBackingArray(); 983 backingArray[valueStartPos+1] = (byte) ((length >> 8) & 0xFF); 984 backingArray[valueStartPos+2] = (byte) (length & 0xFF); 985 } 986 else if ((length & 0x00FF_FFFF) == length) 987 { 988 buffer.insert(valueStartPos, MULTIBYTE_LENGTH_HEADER_PLUS_THREE); 989 990 final byte[] backingArray = buffer.getBackingArray(); 991 backingArray[valueStartPos+1] = (byte) ((length >> 16) & 0xFF); 992 backingArray[valueStartPos+2] = (byte) ((length >> 8) & 0xFF); 993 backingArray[valueStartPos+3] = (byte) (length & 0xFF); 994 } 995 else 996 { 997 buffer.insert(valueStartPos, MULTIBYTE_LENGTH_HEADER_PLUS_FOUR); 998 999 final byte[] backingArray = buffer.getBackingArray(); 1000 backingArray[valueStartPos+1] = (byte) ((length >> 24) & 0xFF); 1001 backingArray[valueStartPos+2] = (byte) ((length >> 16) & 0xFF); 1002 backingArray[valueStartPos+3] = (byte) ((length >> 8) & 0xFF); 1003 backingArray[valueStartPos+4] = (byte) (length & 0xFF); 1004 } 1005 } 1006 1007 1008 1009 /** 1010 * Writes the contents of this buffer to the provided output stream. 1011 * 1012 * @param outputStream The output stream to which the data should be 1013 * written. 1014 * 1015 * @throws IOException If a problem occurs while writing to the provided 1016 * output stream. 1017 */ 1018 public void writeTo(final OutputStream outputStream) 1019 throws IOException 1020 { 1021 if (Debug.debugEnabled(DebugType.ASN1)) 1022 { 1023 Debug.debugASN1Write(this); 1024 } 1025 1026 buffer.write(outputStream); 1027 } 1028 1029 1030 1031 /** 1032 * Retrieves a byte array containing the contents of this ASN.1 buffer. 1033 * 1034 * @return A byte array containing the contents of this ASN.1 buffer. 1035 */ 1036 public byte[] toByteArray() 1037 { 1038 return buffer.toByteArray(); 1039 } 1040 1041 1042 1043 /** 1044 * Retrieves a byte buffer that wraps the data associated with this ASN.1 1045 * buffer. The position will be set to the beginning of the data, and the 1046 * limit will be set to one byte after the end of the data. The contents 1047 * of the returned byte buffer must not be altered in any way, and the 1048 * contents of this ASN.1 buffer must not be altered until the 1049 * {@code ByteBuffer} is no longer needed. 1050 * 1051 * @return A byte buffer that wraps the data associated with this ASN.1 1052 * buffer. 1053 */ 1054 public ByteBuffer asByteBuffer() 1055 { 1056 return ByteBuffer.wrap(buffer.getBackingArray(), 0, buffer.length()); 1057 } 1058}