0001: /*
0002: * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved.
0003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004: *
0005: * This code is free software; you can redistribute it and/or modify it
0006: * under the terms of the GNU General Public License version 2 only, as
0007: * published by the Free Software Foundation. Sun designates this
0008: * particular file as subject to the "Classpath" exception as provided
0009: * by Sun in the LICENSE file that accompanied this code.
0010: *
0011: * This code is distributed in the hope that it will be useful, but WITHOUT
0012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0014: * version 2 for more details (a copy is included in the LICENSE file that
0015: * accompanied this code).
0016: *
0017: * You should have received a copy of the GNU General Public License version
0018: * 2 along with this work; if not, write to the Free Software Foundation,
0019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020: *
0021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022: * CA 95054 USA or visit www.sun.com if you need additional information or
0023: * have any questions.
0024: */
0025:
0026: package sun.security.pkcs11;
0027:
0028: import java.io.*;
0029: import java.math.BigInteger;
0030: import java.util.*;
0031:
0032: import java.security.*;
0033: import java.security.interfaces.*;
0034: import java.security.spec.*;
0035:
0036: import javax.crypto.*;
0037: import javax.crypto.interfaces.*;
0038: import javax.crypto.spec.*;
0039:
0040: import sun.security.rsa.RSAPublicKeyImpl;
0041:
0042: import sun.security.internal.interfaces.TlsMasterSecret;
0043:
0044: import sun.security.pkcs11.wrapper.*;
0045: import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
0046:
0047: /**
0048: * Key implementation classes.
0049: *
0050: * In PKCS#11, the components of private and secret keys may or may not
0051: * be accessible. If they are, we use the algorithm specific key classes
0052: * (e.g. DSAPrivateKey) for compatibility with existing applications.
0053: * If the components are not accessible, we use a generic class that
0054: * only implements PrivateKey (or SecretKey). Whether the components of a
0055: * key are extractable is automatically determined when the key object is
0056: * created.
0057: *
0058: * @author Andreas Sterbenz
0059: * @version 1.14, 05/05/07
0060: * @since 1.5
0061: */
0062: abstract class P11Key implements Key {
0063:
0064: private final static String PUBLIC = "public";
0065: private final static String PRIVATE = "private";
0066: private final static String SECRET = "secret";
0067:
0068: // type of key, one of (PUBLIC, PRIVATE, SECRET)
0069: final String type;
0070:
0071: // session in which the key was created, relevant for session objects
0072: final Session session;
0073:
0074: // token instance
0075: final Token token;
0076:
0077: // algorithm name, returned by getAlgorithm(), etc.
0078: final String algorithm;
0079:
0080: // key id
0081: final long keyID;
0082:
0083: // effective key length of the key, e.g. 56 for a DES key
0084: final int keyLength;
0085:
0086: // flags indicating whether the key is a token object, sensitive, extractable
0087: final boolean tokenObject, sensitive, extractable;
0088:
0089: P11Key(String type, Session session, long keyID, String algorithm,
0090: int keyLength, CK_ATTRIBUTE[] attributes) {
0091: this .type = type;
0092: this .session = session;
0093: this .token = session.token;
0094: this .keyID = keyID;
0095: this .algorithm = algorithm;
0096: this .keyLength = keyLength;
0097: boolean tokenObject = false;
0098: boolean sensitive = false;
0099: boolean extractable = true;
0100: int n = (attributes == null) ? 0 : attributes.length;
0101: for (int i = 0; i < n; i++) {
0102: CK_ATTRIBUTE attr = attributes[i];
0103: if (attr.type == CKA_TOKEN) {
0104: tokenObject = attr.getBoolean();
0105: } else if (attr.type == CKA_SENSITIVE) {
0106: sensitive = attr.getBoolean();
0107: } else if (attr.type == CKA_EXTRACTABLE) {
0108: extractable = attr.getBoolean();
0109: }
0110: }
0111: this .tokenObject = tokenObject;
0112: this .sensitive = sensitive;
0113: this .extractable = extractable;
0114: if (tokenObject == false) {
0115: session.addObject();
0116: }
0117: }
0118:
0119: // see JCA spec
0120: public final String getAlgorithm() {
0121: token.ensureValid();
0122: return algorithm;
0123: }
0124:
0125: // see JCA spec
0126: public final byte[] getEncoded() {
0127: byte[] b = getEncodedInternal();
0128: return (b == null) ? null : (byte[]) b.clone();
0129: }
0130:
0131: abstract byte[] getEncodedInternal();
0132:
0133: public boolean equals(Object obj) {
0134: if (this == obj) {
0135: return true;
0136: }
0137: // equals() should never throw exceptions
0138: if (token.isValid() == false) {
0139: return false;
0140: }
0141: if (obj instanceof Key == false) {
0142: return false;
0143: }
0144: String this Format = getFormat();
0145: if (this Format == null) {
0146: // no encoding, key only equal to itself
0147: // XXX getEncoded() for unextractable keys will change that
0148: return false;
0149: }
0150: Key other = (Key) obj;
0151: if (this Format.equals(other.getFormat()) == false) {
0152: return false;
0153: }
0154: byte[] this Enc = this .getEncodedInternal();
0155: byte[] otherEnc;
0156: if (obj instanceof P11Key) {
0157: otherEnc = ((P11Key) other).getEncodedInternal();
0158: } else {
0159: otherEnc = other.getEncoded();
0160: }
0161: return Arrays.equals(this Enc, otherEnc);
0162: }
0163:
0164: public int hashCode() {
0165: // hashCode() should never throw exceptions
0166: if (token.isValid() == false) {
0167: return 0;
0168: }
0169: byte[] b1 = getEncodedInternal();
0170: if (b1 == null) {
0171: return 0;
0172: }
0173: int r = b1.length;
0174: for (int i = 0; i < b1.length; i++) {
0175: r += (b1[i] & 0xff) * 37;
0176: }
0177: return r;
0178: }
0179:
0180: protected Object writeReplace() throws ObjectStreamException {
0181: KeyRep.Type type;
0182: String format = getFormat();
0183: if (isPrivate() && "PKCS#8".equals(format)) {
0184: type = KeyRep.Type.PRIVATE;
0185: } else if (isPublic() && "X.509".equals(format)) {
0186: type = KeyRep.Type.PUBLIC;
0187: } else if (isSecret() && "RAW".equals(format)) {
0188: type = KeyRep.Type.SECRET;
0189: } else {
0190: // XXX short term serialization for unextractable keys
0191: throw new NotSerializableException(
0192: "Cannot serialize sensitive and unextractable keys");
0193: }
0194: return new KeyRep(type, getAlgorithm(), format, getEncoded());
0195: }
0196:
0197: public String toString() {
0198: token.ensureValid();
0199: String s1 = token.provider.getName() + " " + algorithm + " "
0200: + type + " key, " + keyLength + " bits";
0201: s1 += " (id " + keyID + ", "
0202: + (tokenObject ? "token" : "session") + " object";
0203: if (isPublic()) {
0204: s1 += ")";
0205: } else {
0206: s1 += ", " + (sensitive ? "" : "not ") + "sensitive";
0207: s1 += ", " + (extractable ? "" : "un") + "extractable)";
0208: }
0209: return s1;
0210: }
0211:
0212: int keyLength() {
0213: return keyLength;
0214: }
0215:
0216: boolean isPublic() {
0217: return type == PUBLIC;
0218: }
0219:
0220: boolean isPrivate() {
0221: return type == PRIVATE;
0222: }
0223:
0224: boolean isSecret() {
0225: return type == SECRET;
0226: }
0227:
0228: void fetchAttributes(CK_ATTRIBUTE[] attributes) {
0229: Session tempSession = null;
0230: try {
0231: tempSession = token.getOpSession();
0232: token.p11.C_GetAttributeValue(tempSession.id(), keyID,
0233: attributes);
0234: } catch (PKCS11Exception e) {
0235: throw new ProviderException(e);
0236: } finally {
0237: token.releaseSession(tempSession);
0238: }
0239: }
0240:
0241: protected void finalize() throws Throwable {
0242: if (tokenObject || (token.isValid() == false)) {
0243: super .finalize();
0244: return;
0245: }
0246: Session newSession = null;
0247: try {
0248: newSession = token.getOpSession();
0249: token.p11.C_DestroyObject(newSession.id(), keyID);
0250: } catch (PKCS11Exception e) {
0251: // ignore
0252: } finally {
0253: token.releaseSession(newSession);
0254: session.removeObject();
0255: super .finalize();
0256: }
0257: }
0258:
0259: private final static CK_ATTRIBUTE[] A0 = new CK_ATTRIBUTE[0];
0260:
0261: private static CK_ATTRIBUTE[] getAttributes(Session session,
0262: long keyID, CK_ATTRIBUTE[] knownAttributes,
0263: CK_ATTRIBUTE[] desiredAttributes) {
0264: if (knownAttributes == null) {
0265: knownAttributes = A0;
0266: }
0267: for (int i = 0; i < desiredAttributes.length; i++) {
0268: // For each desired attribute, check to see if we have the value
0269: // available already. If everything is here, we save a native call.
0270: CK_ATTRIBUTE attr = desiredAttributes[i];
0271: for (CK_ATTRIBUTE known : knownAttributes) {
0272: if ((attr.type == known.type) && (known.pValue != null)) {
0273: attr.pValue = known.pValue;
0274: break; // break inner for loop
0275: }
0276: }
0277: if (attr.pValue == null) {
0278: // nothing found, need to call C_GetAttributeValue()
0279: for (int j = 0; j < i; j++) {
0280: // clear values copied from knownAttributes
0281: desiredAttributes[j].pValue = null;
0282: }
0283: try {
0284: session.token.p11.C_GetAttributeValue(session.id(),
0285: keyID, desiredAttributes);
0286: } catch (PKCS11Exception e) {
0287: throw new ProviderException(e);
0288: }
0289: break; // break loop, goto return
0290: }
0291: }
0292: return desiredAttributes;
0293: }
0294:
0295: static SecretKey secretKey(Session session, long keyID,
0296: String algorithm, int keyLength, CK_ATTRIBUTE[] attributes) {
0297: attributes = getAttributes(session, keyID, attributes,
0298: new CK_ATTRIBUTE[] { new CK_ATTRIBUTE(CKA_TOKEN),
0299: new CK_ATTRIBUTE(CKA_SENSITIVE),
0300: new CK_ATTRIBUTE(CKA_EXTRACTABLE), });
0301: return new P11SecretKey(session, keyID, algorithm, keyLength,
0302: attributes);
0303: }
0304:
0305: static SecretKey masterSecretKey(Session session, long keyID,
0306: String algorithm, int keyLength, CK_ATTRIBUTE[] attributes,
0307: int major, int minor) {
0308: attributes = getAttributes(session, keyID, attributes,
0309: new CK_ATTRIBUTE[] { new CK_ATTRIBUTE(CKA_TOKEN),
0310: new CK_ATTRIBUTE(CKA_SENSITIVE),
0311: new CK_ATTRIBUTE(CKA_EXTRACTABLE), });
0312: return new P11TlsMasterSecretKey(session, keyID, algorithm,
0313: keyLength, attributes, major, minor);
0314: }
0315:
0316: // we assume that all components of public keys are always accessible
0317: static PublicKey publicKey(Session session, long keyID,
0318: String algorithm, int keyLength, CK_ATTRIBUTE[] attributes) {
0319: if (algorithm.equals("RSA")) {
0320: return new P11RSAPublicKey(session, keyID, algorithm,
0321: keyLength, attributes);
0322: } else if (algorithm.equals("DSA")) {
0323: return new P11DSAPublicKey(session, keyID, algorithm,
0324: keyLength, attributes);
0325: } else if (algorithm.equals("DH")) {
0326: return new P11DHPublicKey(session, keyID, algorithm,
0327: keyLength, attributes);
0328: } else if (algorithm.equals("EC")) {
0329: return new P11ECPublicKey(session, keyID, algorithm,
0330: keyLength, attributes);
0331: } else {
0332: throw new ProviderException("Unknown public key algorithm "
0333: + algorithm);
0334: }
0335: }
0336:
0337: static PrivateKey privateKey(Session session, long keyID,
0338: String algorithm, int keyLength, CK_ATTRIBUTE[] attributes) {
0339: attributes = getAttributes(session, keyID, attributes,
0340: new CK_ATTRIBUTE[] { new CK_ATTRIBUTE(CKA_TOKEN),
0341: new CK_ATTRIBUTE(CKA_SENSITIVE),
0342: new CK_ATTRIBUTE(CKA_EXTRACTABLE), });
0343: if (attributes[1].getBoolean()
0344: || (attributes[2].getBoolean() == false)) {
0345: return new P11PrivateKey(session, keyID, algorithm,
0346: keyLength, attributes);
0347: } else {
0348: if (algorithm.equals("RSA")) {
0349: // XXX better test for RSA CRT keys (single getAttributes() call)
0350: // we need to determine whether this is a CRT key
0351: // see if we can obtain the public exponent
0352: // this should also be readable for sensitive/extractable keys
0353: CK_ATTRIBUTE[] attrs2 = new CK_ATTRIBUTE[] { new CK_ATTRIBUTE(
0354: CKA_PUBLIC_EXPONENT), };
0355: boolean crtKey;
0356: try {
0357: session.token.p11.C_GetAttributeValue(session.id(),
0358: keyID, attrs2);
0359: crtKey = (attrs2[0].pValue instanceof byte[]);
0360: } catch (PKCS11Exception e) {
0361: // ignore, assume not available
0362: crtKey = false;
0363: }
0364: if (crtKey) {
0365: return new P11RSAPrivateKey(session, keyID,
0366: algorithm, keyLength, attributes);
0367: } else {
0368: return new P11RSAPrivateNonCRTKey(session, keyID,
0369: algorithm, keyLength, attributes);
0370: }
0371: } else if (algorithm.equals("DSA")) {
0372: return new P11DSAPrivateKey(session, keyID, algorithm,
0373: keyLength, attributes);
0374: } else if (algorithm.equals("DH")) {
0375: return new P11DHPrivateKey(session, keyID, algorithm,
0376: keyLength, attributes);
0377: } else if (algorithm.equals("EC")) {
0378: return new P11ECPrivateKey(session, keyID, algorithm,
0379: keyLength, attributes);
0380: } else {
0381: throw new ProviderException(
0382: "Unknown private key algorithm " + algorithm);
0383: }
0384: }
0385: }
0386:
0387: // class for sensitive and unextractable private keys
0388: private static final class P11PrivateKey extends P11Key implements
0389: PrivateKey {
0390: P11PrivateKey(Session session, long keyID, String algorithm,
0391: int keyLength, CK_ATTRIBUTE[] attributes) {
0392: super (PRIVATE, session, keyID, algorithm, keyLength,
0393: attributes);
0394: }
0395:
0396: // XXX temporary encoding for serialization purposes
0397: public String getFormat() {
0398: token.ensureValid();
0399: return null;
0400: }
0401:
0402: byte[] getEncodedInternal() {
0403: token.ensureValid();
0404: return null;
0405: }
0406: }
0407:
0408: private static class P11SecretKey extends P11Key implements
0409: SecretKey {
0410: private volatile byte[] encoded;
0411:
0412: P11SecretKey(Session session, long keyID, String algorithm,
0413: int keyLength, CK_ATTRIBUTE[] attributes) {
0414: super (SECRET, session, keyID, algorithm, keyLength,
0415: attributes);
0416: }
0417:
0418: public String getFormat() {
0419: token.ensureValid();
0420: if (sensitive || (extractable == false)) {
0421: return null;
0422: } else {
0423: return "RAW";
0424: }
0425: }
0426:
0427: byte[] getEncodedInternal() {
0428: token.ensureValid();
0429: if (getFormat() == null) {
0430: return null;
0431: }
0432: byte[] b = encoded;
0433: if (b == null) {
0434: synchronized (this ) {
0435: b = encoded;
0436: if (b == null) {
0437: Session tempSession = null;
0438: try {
0439: tempSession = token.getOpSession();
0440: CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] { new CK_ATTRIBUTE(
0441: CKA_VALUE), };
0442: token.p11.C_GetAttributeValue(tempSession
0443: .id(), keyID, attributes);
0444: b = attributes[0].getByteArray();
0445: } catch (PKCS11Exception e) {
0446: throw new ProviderException(e);
0447: } finally {
0448: token.releaseSession(tempSession);
0449: }
0450: encoded = b;
0451: }
0452: }
0453: }
0454: return b;
0455: }
0456: }
0457:
0458: private static class P11TlsMasterSecretKey extends P11SecretKey
0459: implements TlsMasterSecret {
0460: private final int majorVersion, minorVersion;
0461:
0462: P11TlsMasterSecretKey(Session session, long keyID,
0463: String algorithm, int keyLength,
0464: CK_ATTRIBUTE[] attributes, int major, int minor) {
0465: super (session, keyID, algorithm, keyLength, attributes);
0466: this .majorVersion = major;
0467: this .minorVersion = minor;
0468: }
0469:
0470: public int getMajorVersion() {
0471: return majorVersion;
0472: }
0473:
0474: public int getMinorVersion() {
0475: return minorVersion;
0476: }
0477: }
0478:
0479: // RSA CRT private key
0480: private static final class P11RSAPrivateKey extends P11Key
0481: implements RSAPrivateCrtKey {
0482: private BigInteger n, e, d, p, q, pe, qe, coeff;
0483: private byte[] encoded;
0484:
0485: P11RSAPrivateKey(Session session, long keyID, String algorithm,
0486: int keyLength, CK_ATTRIBUTE[] attributes) {
0487: super (PRIVATE, session, keyID, algorithm, keyLength,
0488: attributes);
0489: }
0490:
0491: private synchronized void fetchValues() {
0492: token.ensureValid();
0493: if (n != null) {
0494: return;
0495: }
0496: CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
0497: new CK_ATTRIBUTE(CKA_MODULUS),
0498: new CK_ATTRIBUTE(CKA_PUBLIC_EXPONENT),
0499: new CK_ATTRIBUTE(CKA_PRIVATE_EXPONENT),
0500: new CK_ATTRIBUTE(CKA_PRIME_1),
0501: new CK_ATTRIBUTE(CKA_PRIME_2),
0502: new CK_ATTRIBUTE(CKA_EXPONENT_1),
0503: new CK_ATTRIBUTE(CKA_EXPONENT_2),
0504: new CK_ATTRIBUTE(CKA_COEFFICIENT), };
0505: fetchAttributes(attributes);
0506: n = attributes[0].getBigInteger();
0507: e = attributes[1].getBigInteger();
0508: d = attributes[2].getBigInteger();
0509: p = attributes[3].getBigInteger();
0510: q = attributes[4].getBigInteger();
0511: pe = attributes[5].getBigInteger();
0512: qe = attributes[6].getBigInteger();
0513: coeff = attributes[7].getBigInteger();
0514: }
0515:
0516: public String getFormat() {
0517: token.ensureValid();
0518: return "PKCS#8";
0519: }
0520:
0521: synchronized byte[] getEncodedInternal() {
0522: token.ensureValid();
0523: if (encoded == null) {
0524: fetchValues();
0525: try {
0526: // XXX make constructor in SunRsaSign provider public
0527: // and call it directly
0528: KeyFactory factory = KeyFactory.getInstance("RSA",
0529: P11Util.getSunRsaSignProvider());
0530: Key newKey = factory.translateKey(this );
0531: encoded = newKey.getEncoded();
0532: } catch (GeneralSecurityException e) {
0533: throw new ProviderException(e);
0534: }
0535: }
0536: return encoded;
0537: }
0538:
0539: public BigInteger getModulus() {
0540: fetchValues();
0541: return n;
0542: }
0543:
0544: public BigInteger getPublicExponent() {
0545: fetchValues();
0546: return e;
0547: }
0548:
0549: public BigInteger getPrivateExponent() {
0550: fetchValues();
0551: return d;
0552: }
0553:
0554: public BigInteger getPrimeP() {
0555: fetchValues();
0556: return p;
0557: }
0558:
0559: public BigInteger getPrimeQ() {
0560: fetchValues();
0561: return q;
0562: }
0563:
0564: public BigInteger getPrimeExponentP() {
0565: fetchValues();
0566: return pe;
0567: }
0568:
0569: public BigInteger getPrimeExponentQ() {
0570: fetchValues();
0571: return qe;
0572: }
0573:
0574: public BigInteger getCrtCoefficient() {
0575: fetchValues();
0576: return coeff;
0577: }
0578:
0579: public String toString() {
0580: fetchValues();
0581: StringBuilder sb = new StringBuilder(super .toString());
0582: sb.append("\n modulus: ");
0583: sb.append(n);
0584: sb.append("\n public exponent: ");
0585: sb.append(e);
0586: sb.append("\n private exponent: ");
0587: sb.append(d);
0588: sb.append("\n prime p: ");
0589: sb.append(p);
0590: sb.append("\n prime q: ");
0591: sb.append(q);
0592: sb.append("\n prime exponent p: ");
0593: sb.append(pe);
0594: sb.append("\n prime exponent q: ");
0595: sb.append(qe);
0596: sb.append("\n crt coefficient: ");
0597: sb.append(coeff);
0598: return sb.toString();
0599: }
0600: }
0601:
0602: // RSA non-CRT private key
0603: private static final class P11RSAPrivateNonCRTKey extends P11Key
0604: implements RSAPrivateKey {
0605: private BigInteger n, d;
0606: private byte[] encoded;
0607:
0608: P11RSAPrivateNonCRTKey(Session session, long keyID,
0609: String algorithm, int keyLength,
0610: CK_ATTRIBUTE[] attributes) {
0611: super (PRIVATE, session, keyID, algorithm, keyLength,
0612: attributes);
0613: }
0614:
0615: private synchronized void fetchValues() {
0616: token.ensureValid();
0617: if (n != null) {
0618: return;
0619: }
0620: CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
0621: new CK_ATTRIBUTE(CKA_MODULUS),
0622: new CK_ATTRIBUTE(CKA_PRIVATE_EXPONENT), };
0623: fetchAttributes(attributes);
0624: n = attributes[0].getBigInteger();
0625: d = attributes[1].getBigInteger();
0626: }
0627:
0628: public String getFormat() {
0629: token.ensureValid();
0630: return "PKCS#8";
0631: }
0632:
0633: synchronized byte[] getEncodedInternal() {
0634: token.ensureValid();
0635: if (encoded == null) {
0636: fetchValues();
0637: try {
0638: // XXX make constructor in SunRsaSign provider public
0639: // and call it directly
0640: KeyFactory factory = KeyFactory.getInstance("RSA",
0641: P11Util.getSunRsaSignProvider());
0642: Key newKey = factory.translateKey(this );
0643: encoded = newKey.getEncoded();
0644: } catch (GeneralSecurityException e) {
0645: throw new ProviderException(e);
0646: }
0647: }
0648: return encoded;
0649: }
0650:
0651: public BigInteger getModulus() {
0652: fetchValues();
0653: return n;
0654: }
0655:
0656: public BigInteger getPrivateExponent() {
0657: fetchValues();
0658: return d;
0659: }
0660:
0661: public String toString() {
0662: fetchValues();
0663: StringBuilder sb = new StringBuilder(super .toString());
0664: sb.append("\n modulus: ");
0665: sb.append(n);
0666: sb.append("\n private exponent: ");
0667: sb.append(d);
0668: return sb.toString();
0669: }
0670: }
0671:
0672: private static final class P11RSAPublicKey extends P11Key implements
0673: RSAPublicKey {
0674: private BigInteger n, e;
0675: private byte[] encoded;
0676:
0677: P11RSAPublicKey(Session session, long keyID, String algorithm,
0678: int keyLength, CK_ATTRIBUTE[] attributes) {
0679: super (PUBLIC, session, keyID, algorithm, keyLength,
0680: attributes);
0681: }
0682:
0683: private synchronized void fetchValues() {
0684: token.ensureValid();
0685: if (n != null) {
0686: return;
0687: }
0688: CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
0689: new CK_ATTRIBUTE(CKA_MODULUS),
0690: new CK_ATTRIBUTE(CKA_PUBLIC_EXPONENT), };
0691: fetchAttributes(attributes);
0692: n = attributes[0].getBigInteger();
0693: e = attributes[1].getBigInteger();
0694: }
0695:
0696: public String getFormat() {
0697: token.ensureValid();
0698: return "X.509";
0699: }
0700:
0701: synchronized byte[] getEncodedInternal() {
0702: token.ensureValid();
0703: if (encoded == null) {
0704: fetchValues();
0705: try {
0706: encoded = new RSAPublicKeyImpl(n, e).getEncoded();
0707: } catch (InvalidKeyException e) {
0708: throw new ProviderException(e);
0709: }
0710: }
0711: return encoded;
0712: }
0713:
0714: public BigInteger getModulus() {
0715: fetchValues();
0716: return n;
0717: }
0718:
0719: public BigInteger getPublicExponent() {
0720: fetchValues();
0721: return e;
0722: }
0723:
0724: public String toString() {
0725: fetchValues();
0726: return super .toString() + "\n modulus: " + n
0727: + "\n public exponent: " + e;
0728: }
0729: }
0730:
0731: private static final class P11DSAPublicKey extends P11Key implements
0732: DSAPublicKey {
0733: private BigInteger y;
0734: private DSAParams params;
0735: private byte[] encoded;
0736:
0737: P11DSAPublicKey(Session session, long keyID, String algorithm,
0738: int keyLength, CK_ATTRIBUTE[] attributes) {
0739: super (PUBLIC, session, keyID, algorithm, keyLength,
0740: attributes);
0741: }
0742:
0743: private synchronized void fetchValues() {
0744: token.ensureValid();
0745: if (y != null) {
0746: return;
0747: }
0748: CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
0749: new CK_ATTRIBUTE(CKA_VALUE),
0750: new CK_ATTRIBUTE(CKA_PRIME),
0751: new CK_ATTRIBUTE(CKA_SUBPRIME),
0752: new CK_ATTRIBUTE(CKA_BASE), };
0753: fetchAttributes(attributes);
0754: y = attributes[0].getBigInteger();
0755: params = new DSAParameterSpec(
0756: attributes[1].getBigInteger(), attributes[2]
0757: .getBigInteger(), attributes[3]
0758: .getBigInteger());
0759: }
0760:
0761: public String getFormat() {
0762: token.ensureValid();
0763: return "X.509";
0764: }
0765:
0766: synchronized byte[] getEncodedInternal() {
0767: token.ensureValid();
0768: if (encoded == null) {
0769: fetchValues();
0770: try {
0771: Key key = new sun.security.provider.DSAPublicKey(y,
0772: params.getP(), params.getQ(), params.getG());
0773: encoded = key.getEncoded();
0774: } catch (InvalidKeyException e) {
0775: throw new ProviderException(e);
0776: }
0777: }
0778: return encoded;
0779: }
0780:
0781: public BigInteger getY() {
0782: fetchValues();
0783: return y;
0784: }
0785:
0786: public DSAParams getParams() {
0787: fetchValues();
0788: return params;
0789: }
0790:
0791: public String toString() {
0792: fetchValues();
0793: return super .toString() + "\n y: " + y + "\n p: "
0794: + params.getP() + "\n q: " + params.getQ()
0795: + "\n g: " + params.getG();
0796: }
0797: }
0798:
0799: private static final class P11DSAPrivateKey extends P11Key
0800: implements DSAPrivateKey {
0801: private BigInteger x;
0802: private DSAParams params;
0803: private byte[] encoded;
0804:
0805: P11DSAPrivateKey(Session session, long keyID, String algorithm,
0806: int keyLength, CK_ATTRIBUTE[] attributes) {
0807: super (PRIVATE, session, keyID, algorithm, keyLength,
0808: attributes);
0809: }
0810:
0811: private synchronized void fetchValues() {
0812: token.ensureValid();
0813: if (x != null) {
0814: return;
0815: }
0816: CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
0817: new CK_ATTRIBUTE(CKA_VALUE),
0818: new CK_ATTRIBUTE(CKA_PRIME),
0819: new CK_ATTRIBUTE(CKA_SUBPRIME),
0820: new CK_ATTRIBUTE(CKA_BASE), };
0821: fetchAttributes(attributes);
0822: x = attributes[0].getBigInteger();
0823: params = new DSAParameterSpec(
0824: attributes[1].getBigInteger(), attributes[2]
0825: .getBigInteger(), attributes[3]
0826: .getBigInteger());
0827: }
0828:
0829: public String getFormat() {
0830: token.ensureValid();
0831: return "PKCS#8";
0832: }
0833:
0834: synchronized byte[] getEncodedInternal() {
0835: token.ensureValid();
0836: if (encoded == null) {
0837: fetchValues();
0838: try {
0839: Key key = new sun.security.provider.DSAPrivateKey(
0840: x, params.getP(), params.getQ(), params
0841: .getG());
0842: encoded = key.getEncoded();
0843: } catch (InvalidKeyException e) {
0844: throw new ProviderException(e);
0845: }
0846: }
0847: return encoded;
0848: }
0849:
0850: public BigInteger getX() {
0851: fetchValues();
0852: return x;
0853: }
0854:
0855: public DSAParams getParams() {
0856: fetchValues();
0857: return params;
0858: }
0859:
0860: public String toString() {
0861: fetchValues();
0862: return super .toString() + "\n x: " + x + "\n p: "
0863: + params.getP() + "\n q: " + params.getQ()
0864: + "\n g: " + params.getG();
0865: }
0866: }
0867:
0868: private static final class P11DHPrivateKey extends P11Key implements
0869: DHPrivateKey {
0870: private BigInteger x;
0871: private DHParameterSpec params;
0872: private byte[] encoded;
0873:
0874: P11DHPrivateKey(Session session, long keyID, String algorithm,
0875: int keyLength, CK_ATTRIBUTE[] attributes) {
0876: super (PRIVATE, session, keyID, algorithm, keyLength,
0877: attributes);
0878: }
0879:
0880: private synchronized void fetchValues() {
0881: token.ensureValid();
0882: if (x != null) {
0883: return;
0884: }
0885: CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
0886: new CK_ATTRIBUTE(CKA_VALUE),
0887: new CK_ATTRIBUTE(CKA_PRIME),
0888: new CK_ATTRIBUTE(CKA_BASE), };
0889: fetchAttributes(attributes);
0890: x = attributes[0].getBigInteger();
0891: params = new DHParameterSpec(attributes[1].getBigInteger(),
0892: attributes[2].getBigInteger());
0893: }
0894:
0895: public String getFormat() {
0896: token.ensureValid();
0897: return "PKCS#8";
0898: }
0899:
0900: synchronized byte[] getEncodedInternal() {
0901: token.ensureValid();
0902: if (encoded == null) {
0903: fetchValues();
0904: try {
0905: DHPrivateKeySpec spec = new DHPrivateKeySpec(x,
0906: params.getP(), params.getG());
0907: KeyFactory kf = KeyFactory.getInstance("DH",
0908: P11Util.getSunJceProvider());
0909: Key key = kf.generatePrivate(spec);
0910: encoded = key.getEncoded();
0911: } catch (GeneralSecurityException e) {
0912: throw new ProviderException(e);
0913: }
0914: }
0915: return encoded;
0916: }
0917:
0918: public BigInteger getX() {
0919: fetchValues();
0920: return x;
0921: }
0922:
0923: public DHParameterSpec getParams() {
0924: fetchValues();
0925: return params;
0926: }
0927:
0928: public String toString() {
0929: fetchValues();
0930: return super .toString() + "\n x: " + x + "\n p: "
0931: + params.getP() + "\n g: " + params.getG();
0932: }
0933: }
0934:
0935: private static final class P11DHPublicKey extends P11Key implements
0936: DHPublicKey {
0937: private BigInteger y;
0938: private DHParameterSpec params;
0939: private byte[] encoded;
0940:
0941: P11DHPublicKey(Session session, long keyID, String algorithm,
0942: int keyLength, CK_ATTRIBUTE[] attributes) {
0943: super (PUBLIC, session, keyID, algorithm, keyLength,
0944: attributes);
0945: }
0946:
0947: private synchronized void fetchValues() {
0948: token.ensureValid();
0949: if (y != null) {
0950: return;
0951: }
0952: CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
0953: new CK_ATTRIBUTE(CKA_VALUE),
0954: new CK_ATTRIBUTE(CKA_PRIME),
0955: new CK_ATTRIBUTE(CKA_BASE), };
0956: fetchAttributes(attributes);
0957: y = attributes[0].getBigInteger();
0958: params = new DHParameterSpec(attributes[1].getBigInteger(),
0959: attributes[2].getBigInteger());
0960: }
0961:
0962: public String getFormat() {
0963: token.ensureValid();
0964: return "X.509";
0965: }
0966:
0967: synchronized byte[] getEncodedInternal() {
0968: token.ensureValid();
0969: if (encoded == null) {
0970: fetchValues();
0971: try {
0972: DHPublicKeySpec spec = new DHPublicKeySpec(y,
0973: params.getP(), params.getG());
0974: KeyFactory kf = KeyFactory.getInstance("DH",
0975: P11Util.getSunJceProvider());
0976: Key key = kf.generatePublic(spec);
0977: encoded = key.getEncoded();
0978: } catch (GeneralSecurityException e) {
0979: throw new ProviderException(e);
0980: }
0981: }
0982: return encoded;
0983: }
0984:
0985: public BigInteger getY() {
0986: fetchValues();
0987: return y;
0988: }
0989:
0990: public DHParameterSpec getParams() {
0991: fetchValues();
0992: return params;
0993: }
0994:
0995: public String toString() {
0996: fetchValues();
0997: return super .toString() + "\n y: " + y + "\n p: "
0998: + params.getP() + "\n g: " + params.getG();
0999: }
1000: }
1001:
1002: private static final class P11ECPrivateKey extends P11Key implements
1003: ECPrivateKey {
1004: private BigInteger s;
1005: private ECParameterSpec params;
1006: private byte[] encoded;
1007:
1008: P11ECPrivateKey(Session session, long keyID, String algorithm,
1009: int keyLength, CK_ATTRIBUTE[] attributes) {
1010: super (PRIVATE, session, keyID, algorithm, keyLength,
1011: attributes);
1012: }
1013:
1014: private synchronized void fetchValues() {
1015: token.ensureValid();
1016: if (s != null) {
1017: return;
1018: }
1019: CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
1020: new CK_ATTRIBUTE(CKA_VALUE),
1021: new CK_ATTRIBUTE(CKA_EC_PARAMS, params), };
1022: fetchAttributes(attributes);
1023: s = attributes[0].getBigInteger();
1024: try {
1025: params = P11ECKeyFactory.decodeParameters(attributes[1]
1026: .getByteArray());
1027: } catch (Exception e) {
1028: throw new RuntimeException(
1029: "Could not parse key values", e);
1030: }
1031: }
1032:
1033: public String getFormat() {
1034: token.ensureValid();
1035: return "PKCS#8";
1036: }
1037:
1038: synchronized byte[] getEncodedInternal() {
1039: token.ensureValid();
1040: if (encoded == null) {
1041: fetchValues();
1042: try {
1043: Key key = new sun.security.ec.ECPrivateKeyImpl(s,
1044: params);
1045: encoded = key.getEncoded();
1046: } catch (InvalidKeyException e) {
1047: throw new ProviderException(e);
1048: }
1049: }
1050: return encoded;
1051: }
1052:
1053: public BigInteger getS() {
1054: fetchValues();
1055: return s;
1056: }
1057:
1058: public ECParameterSpec getParams() {
1059: fetchValues();
1060: return params;
1061: }
1062:
1063: public String toString() {
1064: fetchValues();
1065: return super .toString() + "\n private value: " + s
1066: + "\n parameters: " + params;
1067: }
1068: }
1069:
1070: private static final class P11ECPublicKey extends P11Key implements
1071: ECPublicKey {
1072: private ECPoint w;
1073: private ECParameterSpec params;
1074: private byte[] encoded;
1075:
1076: P11ECPublicKey(Session session, long keyID, String algorithm,
1077: int keyLength, CK_ATTRIBUTE[] attributes) {
1078: super (PUBLIC, session, keyID, algorithm, keyLength,
1079: attributes);
1080: }
1081:
1082: private synchronized void fetchValues() {
1083: token.ensureValid();
1084: if (w != null) {
1085: return;
1086: }
1087: CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
1088: new CK_ATTRIBUTE(CKA_EC_POINT),
1089: new CK_ATTRIBUTE(CKA_EC_PARAMS), };
1090: fetchAttributes(attributes);
1091: try {
1092: params = P11ECKeyFactory.decodeParameters(attributes[1]
1093: .getByteArray());
1094: w = P11ECKeyFactory.decodePoint(attributes[0]
1095: .getByteArray(), params.getCurve());
1096: } catch (Exception e) {
1097: throw new RuntimeException(
1098: "Could not parse key values", e);
1099: }
1100: }
1101:
1102: public String getFormat() {
1103: token.ensureValid();
1104: return "X.509";
1105: }
1106:
1107: synchronized byte[] getEncodedInternal() {
1108: token.ensureValid();
1109: if (encoded == null) {
1110: fetchValues();
1111: try {
1112: Key key = new sun.security.ec.ECPublicKeyImpl(w,
1113: params);
1114: encoded = key.getEncoded();
1115: } catch (InvalidKeyException e) {
1116: throw new ProviderException(e);
1117: }
1118: }
1119: return encoded;
1120: }
1121:
1122: public ECPoint getW() {
1123: fetchValues();
1124: return w;
1125: }
1126:
1127: public ECParameterSpec getParams() {
1128: fetchValues();
1129: return params;
1130: }
1131:
1132: public String toString() {
1133: fetchValues();
1134: return super .toString() + "\n public x coord: "
1135: + w.getAffineX() + "\n public y coord: "
1136: + w.getAffineY() + "\n parameters: " + params;
1137: }
1138: }
1139:
1140: }
|