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