blob: 8949826b19e4e85e09297a1fa17ae527232ef74a [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package sun.security.pkcs11;
27
28import java.io.*;
29import java.math.BigInteger;
30import java.util.*;
31
32import java.security.*;
33import java.security.interfaces.*;
34import java.security.spec.*;
35
36import javax.crypto.*;
37import javax.crypto.interfaces.*;
38import javax.crypto.spec.*;
39
40import sun.security.rsa.RSAPublicKeyImpl;
41
42import sun.security.internal.interfaces.TlsMasterSecret;
43
44import sun.security.pkcs11.wrapper.*;
45import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
46
47/**
48 * Key implementation classes.
49 *
50 * In PKCS#11, the components of private and secret keys may or may not
51 * be accessible. If they are, we use the algorithm specific key classes
52 * (e.g. DSAPrivateKey) for compatibility with existing applications.
53 * If the components are not accessible, we use a generic class that
54 * only implements PrivateKey (or SecretKey). Whether the components of a
55 * key are extractable is automatically determined when the key object is
56 * created.
57 *
58 * @author Andreas Sterbenz
59 * @since 1.5
60 */
61abstract class P11Key implements Key {
62
63 private final static String PUBLIC = "public";
64 private final static String PRIVATE = "private";
65 private final static String SECRET = "secret";
66
67 // type of key, one of (PUBLIC, PRIVATE, SECRET)
68 final String type;
69
70 // session in which the key was created, relevant for session objects
71 final Session session;
72
73 // token instance
74 final Token token;
75
76 // algorithm name, returned by getAlgorithm(), etc.
77 final String algorithm;
78
79 // key id
80 final long keyID;
81
82 // effective key length of the key, e.g. 56 for a DES key
83 final int keyLength;
84
85 // flags indicating whether the key is a token object, sensitive, extractable
86 final boolean tokenObject, sensitive, extractable;
87
88 P11Key(String type, Session session, long keyID, String algorithm,
89 int keyLength, CK_ATTRIBUTE[] attributes) {
90 this.type = type;
91 this.session = session;
92 this.token = session.token;
93 this.keyID = keyID;
94 this.algorithm = algorithm;
95 this.keyLength = keyLength;
96 boolean tokenObject = false;
97 boolean sensitive = false;
98 boolean extractable = true;
99 int n = (attributes == null) ? 0 : attributes.length;
100 for (int i = 0; i < n; i++) {
101 CK_ATTRIBUTE attr = attributes[i];
102 if (attr.type == CKA_TOKEN) {
103 tokenObject = attr.getBoolean();
104 } else if (attr.type == CKA_SENSITIVE) {
105 sensitive = attr.getBoolean();
106 } else if (attr.type == CKA_EXTRACTABLE) {
107 extractable = attr.getBoolean();
108 }
109 }
110 this.tokenObject = tokenObject;
111 this.sensitive = sensitive;
112 this.extractable = extractable;
113 if (tokenObject == false) {
114 session.addObject();
115 }
116 }
117
118 // see JCA spec
119 public final String getAlgorithm() {
120 token.ensureValid();
121 return algorithm;
122 }
123
124 // see JCA spec
125 public final byte[] getEncoded() {
126 byte[] b = getEncodedInternal();
127 return (b == null) ? null : (byte[])b.clone();
128 }
129
130 abstract byte[] getEncodedInternal();
131
132 public boolean equals(Object obj) {
133 if (this == obj) {
134 return true;
135 }
136 // equals() should never throw exceptions
137 if (token.isValid() == false) {
138 return false;
139 }
140 if (obj instanceof Key == false) {
141 return false;
142 }
143 String thisFormat = getFormat();
144 if (thisFormat == null) {
145 // no encoding, key only equal to itself
146 // XXX getEncoded() for unextractable keys will change that
147 return false;
148 }
149 Key other = (Key)obj;
150 if (thisFormat.equals(other.getFormat()) == false) {
151 return false;
152 }
153 byte[] thisEnc = this.getEncodedInternal();
154 byte[] otherEnc;
155 if (obj instanceof P11Key) {
156 otherEnc = ((P11Key)other).getEncodedInternal();
157 } else {
158 otherEnc = other.getEncoded();
159 }
160 return Arrays.equals(thisEnc, otherEnc);
161 }
162
163 public int hashCode() {
164 // hashCode() should never throw exceptions
165 if (token.isValid() == false) {
166 return 0;
167 }
168 byte[] b1 = getEncodedInternal();
169 if (b1 == null) {
170 return 0;
171 }
172 int r = b1.length;
173 for (int i = 0; i < b1.length; i++) {
174 r += (b1[i] & 0xff) * 37;
175 }
176 return r;
177 }
178
179 protected Object writeReplace() throws ObjectStreamException {
180 KeyRep.Type type;
181 String format = getFormat();
182 if (isPrivate() && "PKCS#8".equals(format)) {
183 type = KeyRep.Type.PRIVATE;
184 } else if (isPublic() && "X.509".equals(format)) {
185 type = KeyRep.Type.PUBLIC;
186 } else if (isSecret() && "RAW".equals(format)) {
187 type = KeyRep.Type.SECRET;
188 } else {
189 // XXX short term serialization for unextractable keys
190 throw new NotSerializableException
191 ("Cannot serialize sensitive and unextractable keys");
192 }
193 return new KeyRep(type, getAlgorithm(), format, getEncoded());
194 }
195
196 public String toString() {
197 token.ensureValid();
198 String s1 = token.provider.getName() + " " + algorithm + " " + type
199 + " key, " + keyLength + " bits";
200 s1 += " (id " + keyID + ", "
201 + (tokenObject ? "token" : "session") + " object";
202 if (isPublic()) {
203 s1 += ")";
204 } else {
205 s1 += ", " + (sensitive ? "" : "not ") + "sensitive";
206 s1 += ", " + (extractable ? "" : "un") + "extractable)";
207 }
208 return s1;
209 }
210
211 int keyLength() {
212 return keyLength;
213 }
214
215 boolean isPublic() {
216 return type == PUBLIC;
217 }
218
219 boolean isPrivate() {
220 return type == PRIVATE;
221 }
222
223 boolean isSecret() {
224 return type == SECRET;
225 }
226
227 void fetchAttributes(CK_ATTRIBUTE[] attributes) {
228 Session tempSession = null;
229 try {
230 tempSession = token.getOpSession();
231 token.p11.C_GetAttributeValue(tempSession.id(), keyID, attributes);
232 } catch (PKCS11Exception e) {
233 throw new ProviderException(e);
234 } finally {
235 token.releaseSession(tempSession);
236 }
237 }
238
239 protected void finalize() throws Throwable {
240 if (tokenObject || (token.isValid() == false)) {
241 super.finalize();
242 return;
243 }
244 Session newSession = null;
245 try {
246 newSession = token.getOpSession();
247 token.p11.C_DestroyObject(newSession.id(), keyID);
248 } catch (PKCS11Exception e) {
249 // ignore
250 } finally {
251 token.releaseSession(newSession);
252 session.removeObject();
253 super.finalize();
254 }
255 }
256
257 private final static CK_ATTRIBUTE[] A0 = new CK_ATTRIBUTE[0];
258
259 private static CK_ATTRIBUTE[] getAttributes(Session session, long keyID,
260 CK_ATTRIBUTE[] knownAttributes, CK_ATTRIBUTE[] desiredAttributes) {
261 if (knownAttributes == null) {
262 knownAttributes = A0;
263 }
264 for (int i = 0; i < desiredAttributes.length; i++) {
265 // For each desired attribute, check to see if we have the value
266 // available already. If everything is here, we save a native call.
267 CK_ATTRIBUTE attr = desiredAttributes[i];
268 for (CK_ATTRIBUTE known : knownAttributes) {
269 if ((attr.type == known.type) && (known.pValue != null)) {
270 attr.pValue = known.pValue;
271 break; // break inner for loop
272 }
273 }
274 if (attr.pValue == null) {
275 // nothing found, need to call C_GetAttributeValue()
276 for (int j = 0; j < i; j++) {
277 // clear values copied from knownAttributes
278 desiredAttributes[j].pValue = null;
279 }
280 try {
281 session.token.p11.C_GetAttributeValue
282 (session.id(), keyID, desiredAttributes);
283 } catch (PKCS11Exception e) {
284 throw new ProviderException(e);
285 }
286 break; // break loop, goto return
287 }
288 }
289 return desiredAttributes;
290 }
291
292 static SecretKey secretKey(Session session, long keyID, String algorithm,
293 int keyLength, CK_ATTRIBUTE[] attributes) {
294 attributes = getAttributes(session, keyID, attributes, new CK_ATTRIBUTE[] {
295 new CK_ATTRIBUTE(CKA_TOKEN),
296 new CK_ATTRIBUTE(CKA_SENSITIVE),
297 new CK_ATTRIBUTE(CKA_EXTRACTABLE),
298 });
299 return new P11SecretKey(session, keyID, algorithm, keyLength, attributes);
300 }
301
302 static SecretKey masterSecretKey(Session session, long keyID, String algorithm,
303 int keyLength, CK_ATTRIBUTE[] attributes, int major, int minor) {
304 attributes = getAttributes(session, keyID, attributes, new CK_ATTRIBUTE[] {
305 new CK_ATTRIBUTE(CKA_TOKEN),
306 new CK_ATTRIBUTE(CKA_SENSITIVE),
307 new CK_ATTRIBUTE(CKA_EXTRACTABLE),
308 });
309 return new P11TlsMasterSecretKey
310 (session, keyID, algorithm, keyLength, attributes, major, minor);
311 }
312
313 // we assume that all components of public keys are always accessible
314 static PublicKey publicKey(Session session, long keyID, String algorithm,
315 int keyLength, CK_ATTRIBUTE[] attributes) {
316 if (algorithm.equals("RSA")) {
317 return new P11RSAPublicKey
318 (session, keyID, algorithm, keyLength, attributes);
319 } else if (algorithm.equals("DSA")) {
320 return new P11DSAPublicKey
321 (session, keyID, algorithm, keyLength, attributes);
322 } else if (algorithm.equals("DH")) {
323 return new P11DHPublicKey
324 (session, keyID, algorithm, keyLength, attributes);
325 } else if (algorithm.equals("EC")) {
326 return new P11ECPublicKey
327 (session, keyID, algorithm, keyLength, attributes);
328 } else {
329 throw new ProviderException
330 ("Unknown public key algorithm " + algorithm);
331 }
332 }
333
334 static PrivateKey privateKey(Session session, long keyID, String algorithm,
335 int keyLength, CK_ATTRIBUTE[] attributes) {
336 attributes = getAttributes(session, keyID, attributes, new CK_ATTRIBUTE[] {
337 new CK_ATTRIBUTE(CKA_TOKEN),
338 new CK_ATTRIBUTE(CKA_SENSITIVE),
339 new CK_ATTRIBUTE(CKA_EXTRACTABLE),
340 });
341 if (attributes[1].getBoolean() || (attributes[2].getBoolean() == false)) {
342 return new P11PrivateKey
343 (session, keyID, algorithm, keyLength, attributes);
344 } else {
345 if (algorithm.equals("RSA")) {
346 // XXX better test for RSA CRT keys (single getAttributes() call)
347 // we need to determine whether this is a CRT key
348 // see if we can obtain the public exponent
349 // this should also be readable for sensitive/extractable keys
350 CK_ATTRIBUTE[] attrs2 = new CK_ATTRIBUTE[] {
351 new CK_ATTRIBUTE(CKA_PUBLIC_EXPONENT),
352 };
353 boolean crtKey;
354 try {
355 session.token.p11.C_GetAttributeValue
356 (session.id(), keyID, attrs2);
357 crtKey = (attrs2[0].pValue instanceof byte[]);
358 } catch (PKCS11Exception e) {
359 // ignore, assume not available
360 crtKey = false;
361 }
362 if (crtKey) {
363 return new P11RSAPrivateKey
364 (session, keyID, algorithm, keyLength, attributes);
365 } else {
366 return new P11RSAPrivateNonCRTKey
367 (session, keyID, algorithm, keyLength, attributes);
368 }
369 } else if (algorithm.equals("DSA")) {
370 return new P11DSAPrivateKey
371 (session, keyID, algorithm, keyLength, attributes);
372 } else if (algorithm.equals("DH")) {
373 return new P11DHPrivateKey
374 (session, keyID, algorithm, keyLength, attributes);
375 } else if (algorithm.equals("EC")) {
376 return new P11ECPrivateKey
377 (session, keyID, algorithm, keyLength, attributes);
378 } else {
379 throw new ProviderException
380 ("Unknown private key algorithm " + algorithm);
381 }
382 }
383 }
384
385 // class for sensitive and unextractable private keys
386 private static final class P11PrivateKey extends P11Key
387 implements PrivateKey {
388 P11PrivateKey(Session session, long keyID, String algorithm,
389 int keyLength, CK_ATTRIBUTE[] attributes) {
390 super(PRIVATE, session, keyID, algorithm, keyLength, attributes);
391 }
392 // XXX temporary encoding for serialization purposes
393 public String getFormat() {
394 token.ensureValid();
395 return null;
396 }
397 byte[] getEncodedInternal() {
398 token.ensureValid();
399 return null;
400 }
401 }
402
403 private static class P11SecretKey extends P11Key implements SecretKey {
404 private volatile byte[] encoded;
405 P11SecretKey(Session session, long keyID, String algorithm,
406 int keyLength, CK_ATTRIBUTE[] attributes) {
407 super(SECRET, session, keyID, algorithm, keyLength, attributes);
408 }
409 public String getFormat() {
410 token.ensureValid();
411 if (sensitive || (extractable == false)) {
412 return null;
413 } else {
414 return "RAW";
415 }
416 }
417 byte[] getEncodedInternal() {
418 token.ensureValid();
419 if (getFormat() == null) {
420 return null;
421 }
422 byte[] b = encoded;
423 if (b == null) {
424 synchronized (this) {
425 b = encoded;
426 if (b == null) {
427 Session tempSession = null;
428 try {
429 tempSession = token.getOpSession();
430 CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
431 new CK_ATTRIBUTE(CKA_VALUE),
432 };
433 token.p11.C_GetAttributeValue
434 (tempSession.id(), keyID, attributes);
435 b = attributes[0].getByteArray();
436 } catch (PKCS11Exception e) {
437 throw new ProviderException(e);
438 } finally {
439 token.releaseSession(tempSession);
440 }
441 encoded = b;
442 }
443 }
444 }
445 return b;
446 }
447 }
448
449 private static class P11TlsMasterSecretKey extends P11SecretKey
450 implements TlsMasterSecret {
451 private final int majorVersion, minorVersion;
452 P11TlsMasterSecretKey(Session session, long keyID, String algorithm,
453 int keyLength, CK_ATTRIBUTE[] attributes, int major, int minor) {
454 super(session, keyID, algorithm, keyLength, attributes);
455 this.majorVersion = major;
456 this.minorVersion = minor;
457 }
458 public int getMajorVersion() {
459 return majorVersion;
460 }
461
462 public int getMinorVersion() {
463 return minorVersion;
464 }
465 }
466
467 // RSA CRT private key
468 private static final class P11RSAPrivateKey extends P11Key
469 implements RSAPrivateCrtKey {
470 private BigInteger n, e, d, p, q, pe, qe, coeff;
471 private byte[] encoded;
472 P11RSAPrivateKey(Session session, long keyID, String algorithm,
473 int keyLength, CK_ATTRIBUTE[] attributes) {
474 super(PRIVATE, session, keyID, algorithm, keyLength, attributes);
475 }
476 private synchronized void fetchValues() {
477 token.ensureValid();
478 if (n != null) {
479 return;
480 }
481 CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
482 new CK_ATTRIBUTE(CKA_MODULUS),
483 new CK_ATTRIBUTE(CKA_PUBLIC_EXPONENT),
484 new CK_ATTRIBUTE(CKA_PRIVATE_EXPONENT),
485 new CK_ATTRIBUTE(CKA_PRIME_1),
486 new CK_ATTRIBUTE(CKA_PRIME_2),
487 new CK_ATTRIBUTE(CKA_EXPONENT_1),
488 new CK_ATTRIBUTE(CKA_EXPONENT_2),
489 new CK_ATTRIBUTE(CKA_COEFFICIENT),
490 };
491 fetchAttributes(attributes);
492 n = attributes[0].getBigInteger();
493 e = attributes[1].getBigInteger();
494 d = attributes[2].getBigInteger();
495 p = attributes[3].getBigInteger();
496 q = attributes[4].getBigInteger();
497 pe = attributes[5].getBigInteger();
498 qe = attributes[6].getBigInteger();
499 coeff = attributes[7].getBigInteger();
500 }
501 public String getFormat() {
502 token.ensureValid();
503 return "PKCS#8";
504 }
505 synchronized byte[] getEncodedInternal() {
506 token.ensureValid();
507 if (encoded == null) {
508 fetchValues();
509 try {
510 // XXX make constructor in SunRsaSign provider public
511 // and call it directly
512 KeyFactory factory = KeyFactory.getInstance
513 ("RSA", P11Util.getSunRsaSignProvider());
514 Key newKey = factory.translateKey(this);
515 encoded = newKey.getEncoded();
516 } catch (GeneralSecurityException e) {
517 throw new ProviderException(e);
518 }
519 }
520 return encoded;
521 }
522 public BigInteger getModulus() {
523 fetchValues();
524 return n;
525 }
526 public BigInteger getPublicExponent() {
527 fetchValues();
528 return e;
529 }
530 public BigInteger getPrivateExponent() {
531 fetchValues();
532 return d;
533 }
534 public BigInteger getPrimeP() {
535 fetchValues();
536 return p;
537 }
538 public BigInteger getPrimeQ() {
539 fetchValues();
540 return q;
541 }
542 public BigInteger getPrimeExponentP() {
543 fetchValues();
544 return pe;
545 }
546 public BigInteger getPrimeExponentQ() {
547 fetchValues();
548 return qe;
549 }
550 public BigInteger getCrtCoefficient() {
551 fetchValues();
552 return coeff;
553 }
554 public String toString() {
555 fetchValues();
556 StringBuilder sb = new StringBuilder(super.toString());
557 sb.append("\n modulus: ");
558 sb.append(n);
559 sb.append("\n public exponent: ");
560 sb.append(e);
561 sb.append("\n private exponent: ");
562 sb.append(d);
563 sb.append("\n prime p: ");
564 sb.append(p);
565 sb.append("\n prime q: ");
566 sb.append(q);
567 sb.append("\n prime exponent p: ");
568 sb.append(pe);
569 sb.append("\n prime exponent q: ");
570 sb.append(qe);
571 sb.append("\n crt coefficient: ");
572 sb.append(coeff);
573 return sb.toString();
574 }
575 }
576
577 // RSA non-CRT private key
578 private static final class P11RSAPrivateNonCRTKey extends P11Key
579 implements RSAPrivateKey {
580 private BigInteger n, d;
581 private byte[] encoded;
582 P11RSAPrivateNonCRTKey(Session session, long keyID, String algorithm,
583 int keyLength, CK_ATTRIBUTE[] attributes) {
584 super(PRIVATE, session, keyID, algorithm, keyLength, attributes);
585 }
586 private synchronized void fetchValues() {
587 token.ensureValid();
588 if (n != null) {
589 return;
590 }
591 CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
592 new CK_ATTRIBUTE(CKA_MODULUS),
593 new CK_ATTRIBUTE(CKA_PRIVATE_EXPONENT),
594 };
595 fetchAttributes(attributes);
596 n = attributes[0].getBigInteger();
597 d = attributes[1].getBigInteger();
598 }
599 public String getFormat() {
600 token.ensureValid();
601 return "PKCS#8";
602 }
603 synchronized byte[] getEncodedInternal() {
604 token.ensureValid();
605 if (encoded == null) {
606 fetchValues();
607 try {
608 // XXX make constructor in SunRsaSign provider public
609 // and call it directly
610 KeyFactory factory = KeyFactory.getInstance
611 ("RSA", P11Util.getSunRsaSignProvider());
612 Key newKey = factory.translateKey(this);
613 encoded = newKey.getEncoded();
614 } catch (GeneralSecurityException e) {
615 throw new ProviderException(e);
616 }
617 }
618 return encoded;
619 }
620 public BigInteger getModulus() {
621 fetchValues();
622 return n;
623 }
624 public BigInteger getPrivateExponent() {
625 fetchValues();
626 return d;
627 }
628 public String toString() {
629 fetchValues();
630 StringBuilder sb = new StringBuilder(super.toString());
631 sb.append("\n modulus: ");
632 sb.append(n);
633 sb.append("\n private exponent: ");
634 sb.append(d);
635 return sb.toString();
636 }
637 }
638
639 private static final class P11RSAPublicKey extends P11Key
640 implements RSAPublicKey {
641 private BigInteger n, e;
642 private byte[] encoded;
643 P11RSAPublicKey(Session session, long keyID, String algorithm,
644 int keyLength, CK_ATTRIBUTE[] attributes) {
645 super(PUBLIC, session, keyID, algorithm, keyLength, attributes);
646 }
647 private synchronized void fetchValues() {
648 token.ensureValid();
649 if (n != null) {
650 return;
651 }
652 CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
653 new CK_ATTRIBUTE(CKA_MODULUS),
654 new CK_ATTRIBUTE(CKA_PUBLIC_EXPONENT),
655 };
656 fetchAttributes(attributes);
657 n = attributes[0].getBigInteger();
658 e = attributes[1].getBigInteger();
659 }
660 public String getFormat() {
661 token.ensureValid();
662 return "X.509";
663 }
664 synchronized byte[] getEncodedInternal() {
665 token.ensureValid();
666 if (encoded == null) {
667 fetchValues();
668 try {
669 encoded = new RSAPublicKeyImpl(n, e).getEncoded();
670 } catch (InvalidKeyException e) {
671 throw new ProviderException(e);
672 }
673 }
674 return encoded;
675 }
676 public BigInteger getModulus() {
677 fetchValues();
678 return n;
679 }
680 public BigInteger getPublicExponent() {
681 fetchValues();
682 return e;
683 }
684 public String toString() {
685 fetchValues();
686 return super.toString() + "\n modulus: " + n
687 + "\n public exponent: " + e;
688 }
689 }
690
691 private static final class P11DSAPublicKey extends P11Key
692 implements DSAPublicKey {
693 private BigInteger y;
694 private DSAParams params;
695 private byte[] encoded;
696 P11DSAPublicKey(Session session, long keyID, String algorithm,
697 int keyLength, CK_ATTRIBUTE[] attributes) {
698 super(PUBLIC, session, keyID, algorithm, keyLength, attributes);
699 }
700 private synchronized void fetchValues() {
701 token.ensureValid();
702 if (y != null) {
703 return;
704 }
705 CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
706 new CK_ATTRIBUTE(CKA_VALUE),
707 new CK_ATTRIBUTE(CKA_PRIME),
708 new CK_ATTRIBUTE(CKA_SUBPRIME),
709 new CK_ATTRIBUTE(CKA_BASE),
710 };
711 fetchAttributes(attributes);
712 y = attributes[0].getBigInteger();
713 params = new DSAParameterSpec(
714 attributes[1].getBigInteger(),
715 attributes[2].getBigInteger(),
716 attributes[3].getBigInteger()
717 );
718 }
719 public String getFormat() {
720 token.ensureValid();
721 return "X.509";
722 }
723 synchronized byte[] getEncodedInternal() {
724 token.ensureValid();
725 if (encoded == null) {
726 fetchValues();
727 try {
728 Key key = new sun.security.provider.DSAPublicKey
729 (y, params.getP(), params.getQ(), params.getG());
730 encoded = key.getEncoded();
731 } catch (InvalidKeyException e) {
732 throw new ProviderException(e);
733 }
734 }
735 return encoded;
736 }
737 public BigInteger getY() {
738 fetchValues();
739 return y;
740 }
741 public DSAParams getParams() {
742 fetchValues();
743 return params;
744 }
745 public String toString() {
746 fetchValues();
747 return super.toString() + "\n y: " + y + "\n p: " + params.getP()
748 + "\n q: " + params.getQ() + "\n g: " + params.getG();
749 }
750 }
751
752 private static final class P11DSAPrivateKey extends P11Key
753 implements DSAPrivateKey {
754 private BigInteger x;
755 private DSAParams params;
756 private byte[] encoded;
757 P11DSAPrivateKey(Session session, long keyID, String algorithm,
758 int keyLength, CK_ATTRIBUTE[] attributes) {
759 super(PRIVATE, session, keyID, algorithm, keyLength, attributes);
760 }
761 private synchronized void fetchValues() {
762 token.ensureValid();
763 if (x != null) {
764 return;
765 }
766 CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
767 new CK_ATTRIBUTE(CKA_VALUE),
768 new CK_ATTRIBUTE(CKA_PRIME),
769 new CK_ATTRIBUTE(CKA_SUBPRIME),
770 new CK_ATTRIBUTE(CKA_BASE),
771 };
772 fetchAttributes(attributes);
773 x = attributes[0].getBigInteger();
774 params = new DSAParameterSpec(
775 attributes[1].getBigInteger(),
776 attributes[2].getBigInteger(),
777 attributes[3].getBigInteger()
778 );
779 }
780 public String getFormat() {
781 token.ensureValid();
782 return "PKCS#8";
783 }
784 synchronized byte[] getEncodedInternal() {
785 token.ensureValid();
786 if (encoded == null) {
787 fetchValues();
788 try {
789 Key key = new sun.security.provider.DSAPrivateKey
790 (x, params.getP(), params.getQ(), params.getG());
791 encoded = key.getEncoded();
792 } catch (InvalidKeyException e) {
793 throw new ProviderException(e);
794 }
795 }
796 return encoded;
797 }
798 public BigInteger getX() {
799 fetchValues();
800 return x;
801 }
802 public DSAParams getParams() {
803 fetchValues();
804 return params;
805 }
806 public String toString() {
807 fetchValues();
808 return super.toString() + "\n x: " + x + "\n p: " + params.getP()
809 + "\n q: " + params.getQ() + "\n g: " + params.getG();
810 }
811 }
812
813 private static final class P11DHPrivateKey extends P11Key
814 implements DHPrivateKey {
815 private BigInteger x;
816 private DHParameterSpec params;
817 private byte[] encoded;
818 P11DHPrivateKey(Session session, long keyID, String algorithm,
819 int keyLength, CK_ATTRIBUTE[] attributes) {
820 super(PRIVATE, session, keyID, algorithm, keyLength, attributes);
821 }
822 private synchronized void fetchValues() {
823 token.ensureValid();
824 if (x != null) {
825 return;
826 }
827 CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
828 new CK_ATTRIBUTE(CKA_VALUE),
829 new CK_ATTRIBUTE(CKA_PRIME),
830 new CK_ATTRIBUTE(CKA_BASE),
831 };
832 fetchAttributes(attributes);
833 x = attributes[0].getBigInteger();
834 params = new DHParameterSpec(
835 attributes[1].getBigInteger(),
836 attributes[2].getBigInteger()
837 );
838 }
839 public String getFormat() {
840 token.ensureValid();
841 return "PKCS#8";
842 }
843 synchronized byte[] getEncodedInternal() {
844 token.ensureValid();
845 if (encoded == null) {
846 fetchValues();
847 try {
848 DHPrivateKeySpec spec = new DHPrivateKeySpec
849 (x, params.getP(), params.getG());
850 KeyFactory kf = KeyFactory.getInstance
851 ("DH", P11Util.getSunJceProvider());
852 Key key = kf.generatePrivate(spec);
853 encoded = key.getEncoded();
854 } catch (GeneralSecurityException e) {
855 throw new ProviderException(e);
856 }
857 }
858 return encoded;
859 }
860 public BigInteger getX() {
861 fetchValues();
862 return x;
863 }
864 public DHParameterSpec getParams() {
865 fetchValues();
866 return params;
867 }
868 public String toString() {
869 fetchValues();
870 return super.toString() + "\n x: " + x + "\n p: " + params.getP()
871 + "\n g: " + params.getG();
872 }
873 }
874
875 private static final class P11DHPublicKey extends P11Key
876 implements DHPublicKey {
877 private BigInteger y;
878 private DHParameterSpec params;
879 private byte[] encoded;
880 P11DHPublicKey(Session session, long keyID, String algorithm,
881 int keyLength, CK_ATTRIBUTE[] attributes) {
882 super(PUBLIC, session, keyID, algorithm, keyLength, attributes);
883 }
884 private synchronized void fetchValues() {
885 token.ensureValid();
886 if (y != null) {
887 return;
888 }
889 CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
890 new CK_ATTRIBUTE(CKA_VALUE),
891 new CK_ATTRIBUTE(CKA_PRIME),
892 new CK_ATTRIBUTE(CKA_BASE),
893 };
894 fetchAttributes(attributes);
895 y = attributes[0].getBigInteger();
896 params = new DHParameterSpec(
897 attributes[1].getBigInteger(),
898 attributes[2].getBigInteger()
899 );
900 }
901 public String getFormat() {
902 token.ensureValid();
903 return "X.509";
904 }
905 synchronized byte[] getEncodedInternal() {
906 token.ensureValid();
907 if (encoded == null) {
908 fetchValues();
909 try {
910 DHPublicKeySpec spec = new DHPublicKeySpec
911 (y, params.getP(), params.getG());
912 KeyFactory kf = KeyFactory.getInstance
913 ("DH", P11Util.getSunJceProvider());
914 Key key = kf.generatePublic(spec);
915 encoded = key.getEncoded();
916 } catch (GeneralSecurityException e) {
917 throw new ProviderException(e);
918 }
919 }
920 return encoded;
921 }
922 public BigInteger getY() {
923 fetchValues();
924 return y;
925 }
926 public DHParameterSpec getParams() {
927 fetchValues();
928 return params;
929 }
930 public String toString() {
931 fetchValues();
932 return super.toString() + "\n y: " + y + "\n p: " + params.getP()
933 + "\n g: " + params.getG();
934 }
935 }
936
937 private static final class P11ECPrivateKey extends P11Key
938 implements ECPrivateKey {
939 private BigInteger s;
940 private ECParameterSpec params;
941 private byte[] encoded;
942 P11ECPrivateKey(Session session, long keyID, String algorithm,
943 int keyLength, CK_ATTRIBUTE[] attributes) {
944 super(PRIVATE, session, keyID, algorithm, keyLength, attributes);
945 }
946 private synchronized void fetchValues() {
947 token.ensureValid();
948 if (s != null) {
949 return;
950 }
951 CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
952 new CK_ATTRIBUTE(CKA_VALUE),
953 new CK_ATTRIBUTE(CKA_EC_PARAMS, params),
954 };
955 fetchAttributes(attributes);
956 s = attributes[0].getBigInteger();
957 try {
958 params = P11ECKeyFactory.decodeParameters
959 (attributes[1].getByteArray());
960 } catch (Exception e) {
961 throw new RuntimeException("Could not parse key values", e);
962 }
963 }
964 public String getFormat() {
965 token.ensureValid();
966 return "PKCS#8";
967 }
968 synchronized byte[] getEncodedInternal() {
969 token.ensureValid();
970 if (encoded == null) {
971 fetchValues();
972 try {
973 Key key = new sun.security.ec.ECPrivateKeyImpl(s, params);
974 encoded = key.getEncoded();
975 } catch (InvalidKeyException e) {
976 throw new ProviderException(e);
977 }
978 }
979 return encoded;
980 }
981 public BigInteger getS() {
982 fetchValues();
983 return s;
984 }
985 public ECParameterSpec getParams() {
986 fetchValues();
987 return params;
988 }
989 public String toString() {
990 fetchValues();
991 return super.toString()
992 + "\n private value: " + s
993 + "\n parameters: " + params;
994 }
995 }
996
997 private static final class P11ECPublicKey extends P11Key
998 implements ECPublicKey {
999 private ECPoint w;
1000 private ECParameterSpec params;
1001 private byte[] encoded;
1002 P11ECPublicKey(Session session, long keyID, String algorithm,
1003 int keyLength, CK_ATTRIBUTE[] attributes) {
1004 super(PUBLIC, session, keyID, algorithm, keyLength, attributes);
1005 }
1006 private synchronized void fetchValues() {
1007 token.ensureValid();
1008 if (w != null) {
1009 return;
1010 }
1011 CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
1012 new CK_ATTRIBUTE(CKA_EC_POINT),
1013 new CK_ATTRIBUTE(CKA_EC_PARAMS),
1014 };
1015 fetchAttributes(attributes);
1016 try {
1017 params = P11ECKeyFactory.decodeParameters
1018 (attributes[1].getByteArray());
1019 w = P11ECKeyFactory.decodePoint
1020 (attributes[0].getByteArray(), params.getCurve());
1021 } catch (Exception e) {
1022 throw new RuntimeException("Could not parse key values", e);
1023 }
1024 }
1025 public String getFormat() {
1026 token.ensureValid();
1027 return "X.509";
1028 }
1029 synchronized byte[] getEncodedInternal() {
1030 token.ensureValid();
1031 if (encoded == null) {
1032 fetchValues();
1033 try {
1034 Key key = new sun.security.ec.ECPublicKeyImpl(w, params);
1035 encoded = key.getEncoded();
1036 } catch (InvalidKeyException e) {
1037 throw new ProviderException(e);
1038 }
1039 }
1040 return encoded;
1041 }
1042 public ECPoint getW() {
1043 fetchValues();
1044 return w;
1045 }
1046 public ECParameterSpec getParams() {
1047 fetchValues();
1048 return params;
1049 }
1050 public String toString() {
1051 fetchValues();
1052 return super.toString()
1053 + "\n public x coord: " + w.getAffineX()
1054 + "\n public y coord: " + w.getAffineY()
1055 + "\n parameters: " + params;
1056 }
1057 }
1058
1059}