1 package iaik.pkcs.pkcs11.objects; 2 3 import iaik.pkcs.pkcs11.Session; 4 import iaik.pkcs.pkcs11.TokenException; 5 import iaik.pkcs.pkcs11.wrapper.Constants; 6 import iaik.pkcs.pkcs11.wrapper.PKCS11Constants; 7 import iaik.pkcs.pkcs11.wrapper.PKCS11Exception; 8 9 /** 10 * This is the base class for private (asymmetric) keys. Objects of this class 11 * represent private keys as specified by PKCS#11 v2.11. 12 * 13 * @author Karl Scheibelhofer 14 * @version 1.0 15 * @invariants (subject_ <> null) 16 * and (sensitive_ <> null) 17 * and (secondaryAuth_ <> null) 18 * and (authPinFlags_ <> null) 19 * and (decrypt_ <> null) 20 * and (sign_ <> null) 21 * and (signRecover_ <> null) 22 * and (unwrap_ <> null) 23 * and (extractable_ <> null) 24 * and (alwaysSensitive_ <> null) 25 * and (neverExtractable_ <> null) 26 */ 27 public class PrivateKey extends Key { 28 29 /** 30 * The subject of this private key. 31 */ 32 protected ByteArrayAttribute subject_; 33 34 /** 35 * True, if this private key is sensitive. 36 */ 37 protected BooleanAttribute sensitive_; 38 39 /** 40 * True, if this private key supports secondary authentication. 41 */ 42 protected BooleanAttribute secondaryAuth_; 43 44 /** 45 * The authentication flags for secondary authentication. Only defined, if 46 * the secondaryAuth_ is set. 47 */ 48 protected LongAttribute authPinFlags_; 49 50 /** 51 * True, if this private key can be used for encryption. 52 */ 53 protected BooleanAttribute decrypt_; 54 55 /** 56 * True, if this private key can be used for signing. 57 */ 58 protected BooleanAttribute sign_; 59 60 /** 61 * True, if this private key can be used for signing with recover. 62 */ 63 protected BooleanAttribute signRecover_; 64 65 /** 66 * True, if this private key can be used for unwrapping wrapped keys. 67 */ 68 protected BooleanAttribute unwrap_; 69 70 /** 71 * True, if this private key can not be extracted from the token. 72 */ 73 protected BooleanAttribute extractable_; 74 75 /** 76 * True, if this private key was always sensitive. 77 */ 78 protected BooleanAttribute alwaysSensitive_; 79 80 /** 81 * True, if this private key was never extractable. 82 */ 83 protected BooleanAttribute neverExtractable_; 84 85 /** 86 * True, if this private key can only be wrapped with a wrapping key 87 * having set the attribute trusted to true. 88 */ 89 protected BooleanAttribute wrapWithTrusted_; 90 91 /** 92 * Template of the key, that can be unwrapped. 93 */ 94 protected AttributeArray unwrapTemplate_; 95 96 /** 97 * True, if the user has to supply the PIN for each use 98 * (sign or decrypt) with the key. 99 */ 100 protected BooleanAttribute alwaysAuthenticate_; 101 102 /** 103 * Default Constructor. 104 * 105 * @preconditions 106 * @postconditions 107 */ PrivateKey()108 public PrivateKey() { 109 super(); 110 objectClass_.setLongValue(ObjectClass.PRIVATE_KEY); 111 } 112 113 /** 114 * Called by sub-classes to create an instance of a PKCS#11 private key. 115 * 116 * @param session The session to use for reading attributes. 117 * This session must have the appropriate rights; i.e. 118 * it must be a user-session, if it is a private object. 119 * @param objectHandle The object handle as given from the PKCS#111 module. 120 * @exception TokenException If getting the attributes failed. 121 * @preconditions (session <> null) 122 * @postconditions 123 */ PrivateKey(Session session, long objectHandle)124 protected PrivateKey(Session session, long objectHandle) 125 throws TokenException 126 { 127 super(session, objectHandle); 128 objectClass_.setLongValue(ObjectClass.PRIVATE_KEY); 129 } 130 131 /** 132 * The getInstance method of the Object class uses this method to create 133 * an instance of a PKCS#11 private key. This method reads the key 134 * type attribute and calls the getInstance method of the according sub-class. 135 * If the key type is a vendor defined it uses the 136 * VendorDefinedKeyBuilder set by the application. If no private key 137 * could be constructed, this method returns null. 138 * 139 * @param session The session to use for reading attributes. 140 * This session must have the appropriate rights; i.e. 141 * it must be a user-session, if it is a private object. 142 * @param objectHandle The object handle as given from the PKCS#111 module. 143 * @return The object representing the PKCS#11 object. 144 * The returned object can be casted to the 145 * according sub-class. 146 * @exception TokenException If getting the attributes failed. 147 * @preconditions (session <> null) 148 * @postconditions (result <> null) 149 */ getInstance(Session session, long objectHandle)150 public static Object getInstance(Session session, long objectHandle) 151 throws TokenException 152 { 153 if (session == null) { 154 throw new NullPointerException("Argument \"session\" must not be null."); 155 } 156 157 KeyTypeAttribute keyTypeAttribute = new KeyTypeAttribute(); 158 getAttributeValue(session, objectHandle, keyTypeAttribute); 159 160 Long keyType = keyTypeAttribute.getLongValue(); 161 162 Object newObject; 163 164 if (keyTypeAttribute.isPresent() && (keyType != null)) { 165 if (keyType.equals(Key.KeyType.RSA)) { 166 newObject = RSAPrivateKey.getInstance(session, objectHandle); 167 } else if (keyType.equals(Key.KeyType.DSA)) { 168 newObject = DSAPrivateKey.getInstance(session, objectHandle); 169 } else if (keyType.equals(Key.KeyType.ECDSA)) { 170 newObject = ECDSAPrivateKey.getInstance(session, objectHandle); 171 } else if (keyType.equals(Key.KeyType.DH)) { 172 newObject = DHPrivateKey.getInstance(session, objectHandle); 173 } else if (keyType.equals(Key.KeyType.KEA)) { 174 newObject = KEAPrivateKey.getInstance(session, objectHandle); 175 } else if (keyType.equals(Key.KeyType.X9_42_DH)) { 176 newObject = X942DHPrivateKey.getInstance(session, objectHandle); 177 } else if ((keyType.longValue() & KeyType.VENDOR_DEFINED.longValue()) != 0L) { 178 newObject = getUnknownPrivateKey(session, objectHandle); 179 } else { 180 newObject = getUnknownPrivateKey(session, objectHandle); 181 } 182 } else { 183 newObject = getUnknownPrivateKey(session, objectHandle); 184 } 185 186 return newObject; 187 } 188 189 /** 190 * Try to create a key which has no or an unkown private key type 191 * type attribute. 192 * This implementation will try to use a vendor defined key 193 * builder, if such has been set. 194 * If this is impossible or fails, it will create just 195 * a simple {@link iaik.pkcs.pkcs11.objects.PrivateKey PrivateKey }. 196 * 197 * @param session The session to use. 198 * @param objectHandle The handle of the object 199 * @return A new Object. 200 * @throws TokenException If no object could be created. 201 * @preconditions (session <> null) 202 * @postconditions (result <> null) 203 */ getUnknownPrivateKey(Session session, long objectHandle)204 protected static Object getUnknownPrivateKey(Session session, long objectHandle) 205 throws TokenException 206 { 207 if (session == null) { 208 throw new NullPointerException("Argument \"session\" must not be null."); 209 } 210 211 Object newObject; 212 if (Key.vendorKeyBuilder_ != null) { 213 try { 214 newObject = Key.vendorKeyBuilder_.build(session, objectHandle); 215 } catch (PKCS11Exception ex) { 216 // we can just treat it like some unknown type of private key 217 newObject = new PrivateKey(session, objectHandle); 218 } 219 } else { 220 // we can just treat it like some unknown type of private key 221 newObject = new PrivateKey(session, objectHandle); 222 } 223 224 return newObject; 225 } 226 227 /** 228 * Put all attributes of the given object into the attributes table of this 229 * object. This method is only static to be able to access invoke the 230 * implementation of this method for each class separately (see use in 231 * clone()). 232 * 233 * @param object The object to handle. 234 * @preconditions (object <> null) 235 * @postconditions 236 */ putAttributesInTable(PrivateKey object)237 protected static void putAttributesInTable(PrivateKey object) { 238 if (object == null) { 239 throw new NullPointerException("Argument \"object\" must not be null."); 240 } 241 242 object.attributeTable_.put(Attribute.SUBJECT, object.subject_); 243 object.attributeTable_.put(Attribute.SENSITIVE, object.sensitive_); 244 object.attributeTable_.put(Attribute.SECONDARY_AUTH, object.secondaryAuth_); 245 object.attributeTable_.put(Attribute.AUTH_PIN_FLAGS, object.authPinFlags_); 246 object.attributeTable_.put(Attribute.DECRYPT, object.decrypt_); 247 object.attributeTable_.put(Attribute.SIGN, object.sign_); 248 object.attributeTable_.put(Attribute.SIGN_RECOVER, object.signRecover_); 249 object.attributeTable_.put(Attribute.UNWRAP, object.unwrap_); 250 object.attributeTable_.put(Attribute.EXTRACTABLE, object.extractable_); 251 object.attributeTable_.put(Attribute.ALWAYS_SENSITIVE, object.alwaysSensitive_); 252 object.attributeTable_.put(Attribute.NEVER_EXTRACTABLE, object.neverExtractable_); 253 object.attributeTable_.put(Attribute.WRAP_WITH_TRUSTED, object.wrapWithTrusted_); 254 object.attributeTable_.put(Attribute.UNWRAP_TEMPLATE, object.unwrapTemplate_); 255 object.attributeTable_.put(Attribute.ALWAYS_AUTHENTICATE, object.alwaysAuthenticate_); 256 } 257 258 /** 259 * Allocates the attribute objects for this class and adds them to the 260 * attribute table. 261 * 262 * @preconditions 263 * @postconditions 264 */ allocateAttributes()265 protected void allocateAttributes() { 266 super.allocateAttributes(); 267 268 subject_ = new ByteArrayAttribute(Attribute.SUBJECT); 269 sensitive_ = new BooleanAttribute(Attribute.SENSITIVE); 270 secondaryAuth_ = new BooleanAttribute(Attribute.SECONDARY_AUTH); 271 authPinFlags_ = new LongAttribute(Attribute.AUTH_PIN_FLAGS); 272 decrypt_ = new BooleanAttribute(Attribute.DECRYPT); 273 sign_ = new BooleanAttribute(Attribute.SIGN); 274 signRecover_ = new BooleanAttribute(Attribute.SIGN_RECOVER); 275 unwrap_ = new BooleanAttribute(Attribute.UNWRAP); 276 extractable_ = new BooleanAttribute(Attribute.EXTRACTABLE); 277 alwaysSensitive_ = new BooleanAttribute(Attribute.ALWAYS_SENSITIVE); 278 neverExtractable_ = new BooleanAttribute(Attribute.NEVER_EXTRACTABLE); 279 wrapWithTrusted_ = new BooleanAttribute(Attribute.WRAP_WITH_TRUSTED); 280 unwrapTemplate_ = new AttributeArray(Attribute.UNWRAP_TEMPLATE); 281 alwaysAuthenticate_ = new BooleanAttribute(Attribute.ALWAYS_AUTHENTICATE); 282 283 putAttributesInTable(this); 284 } 285 286 /** 287 * Create a (deep) clone of this object. 288 * 289 * @return A clone of this object. 290 * @preconditions 291 * @postconditions (result <> null) 292 * and (result instanceof PrivateKey) 293 * and (result.equals(this)) 294 */ clone()295 public java.lang.Object clone() { 296 PrivateKey clone = (PrivateKey) super.clone(); 297 298 clone.subject_ = (ByteArrayAttribute) this.subject_.clone(); 299 clone.sensitive_ = (BooleanAttribute) this.sensitive_.clone(); 300 clone.secondaryAuth_ = (BooleanAttribute) this.secondaryAuth_.clone(); 301 clone.authPinFlags_ = (LongAttribute) this.authPinFlags_.clone(); 302 clone.decrypt_ = (BooleanAttribute) this.decrypt_.clone(); 303 clone.sign_ = (BooleanAttribute) this.sign_.clone(); 304 clone.signRecover_ = (BooleanAttribute) this.signRecover_.clone(); 305 clone.unwrap_ = (BooleanAttribute) this.unwrap_.clone(); 306 clone.extractable_ = (BooleanAttribute) this.extractable_.clone(); 307 clone.alwaysSensitive_ = (BooleanAttribute) this.alwaysSensitive_.clone(); 308 clone.neverExtractable_ = (BooleanAttribute) this.neverExtractable_.clone(); 309 clone.wrapWithTrusted_ = (BooleanAttribute) this.wrapWithTrusted_.clone(); 310 clone.unwrapTemplate_ = (AttributeArray) this.unwrapTemplate_.clone(); 311 clone.alwaysAuthenticate_ = (BooleanAttribute) this.alwaysAuthenticate_.clone(); 312 313 putAttributesInTable(clone); // put all cloned attributes into the new table 314 315 return clone; 316 } 317 318 /** 319 * Compares all member variables of this object with the other object. 320 * Returns only true, if all are equal in both objects. 321 * 322 * @param otherObject The other object to compare to. 323 * @return True, if other is an instance of this class and all member 324 * variables of both objects are equal. False, otherwise. 325 * @preconditions 326 * @postconditions 327 */ equals(java.lang.Object otherObject)328 public boolean equals(java.lang.Object otherObject) { 329 boolean equal = false; 330 331 if (otherObject instanceof PrivateKey) { 332 PrivateKey other = (PrivateKey) otherObject; 333 equal = (this == other) 334 || (super.equals(other) && this.subject_.equals(other.subject_) 335 && this.sensitive_.equals(other.sensitive_) 336 && this.secondaryAuth_.equals(other.secondaryAuth_) 337 && this.authPinFlags_.equals(other.authPinFlags_) 338 && this.decrypt_.equals(other.decrypt_) && this.sign_.equals(other.sign_) 339 && this.signRecover_.equals(other.signRecover_) 340 && this.unwrap_.equals(other.unwrap_) 341 && this.extractable_.equals(other.extractable_) 342 && this.alwaysSensitive_.equals(other.alwaysSensitive_) 343 && this.neverExtractable_.equals(other.neverExtractable_) 344 && this.wrapWithTrusted_.equals(other.wrapWithTrusted_) 345 && this.unwrapTemplate_.equals(other.unwrapTemplate_) && this.alwaysAuthenticate_ 346 .equals(other.alwaysAuthenticate_)); 347 } 348 349 return equal; 350 } 351 352 /** 353 * Gets the subject attribute of this key. 354 * 355 * @return The subject attribute. 356 * @preconditions 357 * @postconditions (result <> null) 358 */ getSubject()359 public ByteArrayAttribute getSubject() { 360 return subject_; 361 } 362 363 /** 364 * Gets the sensitive attribute of this key. 365 * 366 * @return The sensitive attribute. 367 * @preconditions 368 * @postconditions (result <> null) 369 */ getSensitive()370 public BooleanAttribute getSensitive() { 371 return sensitive_; 372 } 373 374 /** 375 * Gets the secondary authentication attribute of this key. 376 * 377 * @return The secondary authentication attribute. 378 * @preconditions 379 * @postconditions (result <> null) 380 */ getSecondaryAuth()381 public BooleanAttribute getSecondaryAuth() { 382 return secondaryAuth_; 383 } 384 385 /** 386 * Gets the authentication flags for secondary authentication of this key. 387 * 388 * @return The authentication flags for secondary authentication attribute. 389 * @preconditions 390 * @postconditions (result <> null) 391 */ getAuthPinFlags()392 public LongAttribute getAuthPinFlags() { 393 return authPinFlags_; 394 } 395 396 /** 397 * Gets the decrypt attribute of this key. 398 * 399 * @return The decrypt attribute. 400 * @preconditions 401 * @postconditions (result <> null) 402 */ getDecrypt()403 public BooleanAttribute getDecrypt() { 404 return decrypt_; 405 } 406 407 /** 408 * Gets the sign attribute of this key. 409 * 410 * @return The sign attribute. 411 * @preconditions 412 * @postconditions (result <> null) 413 */ getSign()414 public BooleanAttribute getSign() { 415 return sign_; 416 } 417 418 /** 419 * Gets the sign recover attribute of this key. 420 * 421 * @return The sign recover attribute. 422 * @preconditions 423 * @postconditions (result <> null) 424 */ getSignRecover()425 public BooleanAttribute getSignRecover() { 426 return signRecover_; 427 } 428 429 /** 430 * Gets the unwrap attribute of this key. 431 * 432 * @return The unwrap attribute. 433 * @preconditions 434 * @postconditions (result <> null) 435 */ getUnwrap()436 public BooleanAttribute getUnwrap() { 437 return unwrap_; 438 } 439 440 /** 441 * Gets the extractable attribute of this key. 442 * 443 * @return The extractable attribute. 444 * @preconditions 445 * @postconditions (result <> null) 446 */ getExtractable()447 public BooleanAttribute getExtractable() { 448 return extractable_; 449 } 450 451 /** 452 * Gets the always sensitive attribute of this key. 453 * 454 * @return The always sensitive attribute. 455 * @preconditions 456 * @postconditions (result <> null) 457 */ getAlwaysSensitive()458 public BooleanAttribute getAlwaysSensitive() { 459 return alwaysSensitive_; 460 } 461 462 /** 463 * Gets the never extractable attribute of this key. 464 * 465 * @return The never extractable attribute. 466 * @preconditions 467 * @postconditions (result <> null) 468 */ getNeverExtractable()469 public BooleanAttribute getNeverExtractable() { 470 return neverExtractable_; 471 } 472 473 /** 474 * Gets the wrap with trusted attribute of this key. 475 * 476 * @return The wrap with trusted attribute. 477 * @preconditions 478 * @postconditions (result <> null) 479 */ getWrapWithTrusted()480 public BooleanAttribute getWrapWithTrusted() { 481 return wrapWithTrusted_; 482 } 483 484 /** 485 * Gets the unwrap template attribute of this key. This 486 * attribute can only be used with PKCS#11 modules supporting 487 * cryptoki version 2.20 or higher. 488 * 489 * @return The unwrap template attribute. 490 * @preconditions 491 * @postconditions (result <> null) 492 */ getUnwrapTemplate()493 public AttributeArray getUnwrapTemplate() { 494 return unwrapTemplate_; 495 } 496 497 /** 498 * Gets the always authenticate attribute of this key. 499 * 500 * @return The always authenticate attribute. 501 * @preconditions 502 * @postconditions (result <> null) 503 */ getAlwaysAuthenticate()504 public BooleanAttribute getAlwaysAuthenticate() { 505 return alwaysAuthenticate_; 506 } 507 508 /** 509 * Read the values of the attributes of this object from the token. 510 * 511 * @param session The session handle to use for reading attributes. 512 * This session must have the appropriate rights; i.e. 513 * it must be a user-session, if it is a private object. 514 * @exception TokenException If getting the attributes failed. 515 * @preconditions (session <> null) 516 * @postconditions 517 */ readAttributes(Session session)518 public void readAttributes(Session session) 519 throws TokenException 520 { 521 super.readAttributes(session); 522 523 // Object.getAttributeValue(session, objectHandle_, subject_); 524 // Object.getAttributeValue(session, objectHandle_, sensitive_); 525 // Object.getAttributeValue(session, objectHandle_, secondaryAuth_); 526 // Object.getAttributeValue(session, objectHandle_, authPinFlags_); 527 // Object.getAttributeValue(session, objectHandle_, decrypt_); 528 // Object.getAttributeValue(session, objectHandle_, sign_); 529 // Object.getAttributeValue(session, objectHandle_, signRecover_); 530 // Object.getAttributeValue(session, objectHandle_, unwrap_); 531 // Object.getAttributeValue(session, objectHandle_, extractable_); 532 // Object.getAttributeValue(session, objectHandle_, alwaysSensitive_); 533 // Object.getAttributeValue(session, objectHandle_, neverExtractable_); 534 Object.getAttributeValues(session, objectHandle_, new Attribute[] { subject_, 535 sensitive_, secondaryAuth_, authPinFlags_, decrypt_, sign_, signRecover_, 536 unwrap_, extractable_, alwaysSensitive_, neverExtractable_, wrapWithTrusted_, 537 alwaysAuthenticate_ }); 538 Object.getAttributeValue(session, objectHandle_, unwrapTemplate_); 539 } 540 541 /** 542 * This method returns a string representation of the current object. The 543 * output is only for debugging purposes and should not be used for other 544 * purposes. 545 * 546 * @return A string presentation of this object for debugging output. 547 * @preconditions 548 * @postconditions (result <> null) 549 */ toString()550 public String toString() { 551 StringBuffer buffer = new StringBuffer(1024); 552 553 buffer.append(super.toString()); 554 555 buffer.append(Constants.NEWLINE); 556 buffer.append(Constants.INDENT); 557 buffer.append("Subject (DER, hex): "); 558 buffer.append(subject_.toString()); 559 560 buffer.append(Constants.NEWLINE); 561 buffer.append(Constants.INDENT); 562 buffer.append("Sensitive: "); 563 buffer.append(sensitive_.toString()); 564 565 buffer.append(Constants.NEWLINE); 566 buffer.append(Constants.INDENT); 567 buffer.append("Secondary Authentication: "); 568 buffer.append(secondaryAuth_.toString()); 569 570 buffer.append(Constants.NEWLINE); 571 buffer.append(Constants.INDENT); 572 buffer.append("Secondary Authentication PIN Flags: "); 573 if (authPinFlags_.isPresent() && !authPinFlags_.isSensitive() 574 && (authPinFlags_.getLongValue() != null)) { 575 long authFlagsValue = authPinFlags_.getLongValue().longValue(); 576 577 buffer.append(Constants.NEWLINE); 578 buffer.append(Constants.INDENT); 579 buffer.append(Constants.INDENT); 580 buffer.append("User PIN-Count low: "); 581 buffer.append((authFlagsValue & PKCS11Constants.CKF_USER_PIN_COUNT_LOW) != 0L); 582 583 buffer.append(Constants.NEWLINE); 584 buffer.append(Constants.INDENT); 585 buffer.append(Constants.INDENT); 586 buffer.append("User PIN final Try: "); 587 buffer.append((authFlagsValue & PKCS11Constants.CKF_USER_PIN_FINAL_TRY) != 0L); 588 589 buffer.append(Constants.NEWLINE); 590 buffer.append(Constants.INDENT); 591 buffer.append(Constants.INDENT); 592 buffer.append("User PIN locked: "); 593 buffer.append((authFlagsValue & PKCS11Constants.CKF_USER_PIN_LOCKED) != 0L); 594 595 buffer.append(Constants.NEWLINE); 596 buffer.append(Constants.INDENT); 597 buffer.append(Constants.INDENT); 598 buffer.append("User PIN to be changed: "); 599 buffer.append((authFlagsValue & PKCS11Constants.CKF_USER_PIN_TO_BE_CHANGED) != 0L); 600 } else { 601 buffer.append(authPinFlags_.toString()); 602 } 603 604 buffer.append(Constants.NEWLINE); 605 buffer.append(Constants.INDENT); 606 buffer.append("Decrypt: "); 607 buffer.append(decrypt_.toString()); 608 609 buffer.append(Constants.NEWLINE); 610 buffer.append(Constants.INDENT); 611 buffer.append("Sign: "); 612 buffer.append(sign_.toString()); 613 614 buffer.append(Constants.NEWLINE); 615 buffer.append(Constants.INDENT); 616 buffer.append("Sign Recover: "); 617 buffer.append(signRecover_.toString()); 618 619 buffer.append(Constants.NEWLINE); 620 buffer.append(Constants.INDENT); 621 buffer.append("Unwrap: "); 622 buffer.append(unwrap_.toString()); 623 624 buffer.append(Constants.NEWLINE); 625 buffer.append(Constants.INDENT); 626 buffer.append("Extractable: "); 627 buffer.append(extractable_.toString()); 628 629 buffer.append(Constants.NEWLINE); 630 buffer.append(Constants.INDENT); 631 buffer.append("Always Sensitive: "); 632 buffer.append(alwaysSensitive_.toString()); 633 634 buffer.append(Constants.NEWLINE); 635 buffer.append(Constants.INDENT); 636 buffer.append("Never Extractable: "); 637 buffer.append(neverExtractable_.toString()); 638 639 buffer.append(Constants.NEWLINE); 640 buffer.append(Constants.INDENT); 641 buffer.append("Wrap With Trusted: "); 642 buffer.append(wrapWithTrusted_.toString()); 643 644 buffer.append(Constants.NEWLINE); 645 buffer.append(Constants.INDENT); 646 buffer.append("Unwrap Template: "); 647 buffer.append(unwrapTemplate_.toString()); 648 649 buffer.append(Constants.NEWLINE); 650 buffer.append(Constants.INDENT); 651 buffer.append("Always Authenticate: "); 652 buffer.append(alwaysAuthenticate_.toString()); 653 654 return buffer.toString(); 655 } 656 657 } 658