001: package org.bouncycastle.jce.provider;
002:
003: import org.bouncycastle.asn1.ASN1InputStream;
004: import org.bouncycastle.asn1.ASN1Sequence;
005: import org.bouncycastle.asn1.DERObjectIdentifier;
006: import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
007: import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
008: import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
009: import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
010: import org.bouncycastle.crypto.CipherParameters;
011: import org.bouncycastle.crypto.InvalidCipherTextException;
012: import org.bouncycastle.crypto.Wrapper;
013: import org.bouncycastle.crypto.engines.DESedeEngine;
014: import org.bouncycastle.crypto.engines.DESedeWrapEngine;
015: import org.bouncycastle.crypto.engines.RC2WrapEngine;
016: import org.bouncycastle.crypto.engines.RFC3211WrapEngine;
017: import org.bouncycastle.crypto.params.KeyParameter;
018: import org.bouncycastle.crypto.params.ParametersWithIV;
019:
020: import javax.crypto.BadPaddingException;
021: import javax.crypto.Cipher;
022: import javax.crypto.CipherSpi;
023: import javax.crypto.IllegalBlockSizeException;
024: import javax.crypto.NoSuchPaddingException;
025: import javax.crypto.ShortBufferException;
026: import javax.crypto.spec.IvParameterSpec;
027: import javax.crypto.spec.PBEParameterSpec;
028: import javax.crypto.spec.RC2ParameterSpec;
029: import javax.crypto.spec.RC5ParameterSpec;
030: import javax.crypto.spec.SecretKeySpec;
031: import java.security.AlgorithmParameters;
032: import java.security.InvalidAlgorithmParameterException;
033: import java.security.InvalidKeyException;
034: import java.security.Key;
035: import java.security.KeyFactory;
036: import java.security.NoSuchAlgorithmException;
037: import java.security.NoSuchProviderException;
038: import java.security.PrivateKey;
039: import java.security.SecureRandom;
040: import java.security.spec.AlgorithmParameterSpec;
041: import java.security.spec.InvalidKeySpecException;
042: import java.security.spec.PKCS8EncodedKeySpec;
043: import java.security.spec.X509EncodedKeySpec;
044:
045: public abstract class WrapCipherSpi extends CipherSpi implements PBE {
046: //
047: // specs we can handle.
048: //
049: private Class[] availableSpecs = { IvParameterSpec.class,
050: PBEParameterSpec.class, RC2ParameterSpec.class,
051: RC5ParameterSpec.class };
052:
053: protected int pbeType = PKCS12;
054: protected int pbeHash = SHA1;
055: protected int pbeKeySize;
056: protected int pbeIvSize;
057:
058: protected AlgorithmParameters engineParams = null;
059:
060: protected Wrapper wrapEngine = null;
061:
062: private int ivSize;
063: private byte[] iv;
064:
065: protected WrapCipherSpi() {
066: }
067:
068: protected WrapCipherSpi(Wrapper wrapEngine) {
069: this (wrapEngine, 0);
070: }
071:
072: protected WrapCipherSpi(Wrapper wrapEngine, int ivSize) {
073: this .wrapEngine = wrapEngine;
074: this .ivSize = ivSize;
075: }
076:
077: protected int engineGetBlockSize() {
078: return 0;
079: }
080:
081: protected byte[] engineGetIV() {
082: return (byte[]) iv.clone();
083: }
084:
085: protected int engineGetKeySize(Key key) {
086: return key.getEncoded().length;
087: }
088:
089: protected int engineGetOutputSize(int inputLen) {
090: return -1;
091: }
092:
093: protected AlgorithmParameters engineGetParameters() {
094: return null;
095: }
096:
097: protected void engineSetMode(String mode)
098: throws NoSuchAlgorithmException {
099: throw new NoSuchAlgorithmException("can't support mode " + mode);
100: }
101:
102: protected void engineSetPadding(String padding)
103: throws NoSuchPaddingException {
104: throw new NoSuchPaddingException("Padding " + padding
105: + " unknown.");
106: }
107:
108: protected void engineInit(int opmode, Key key,
109: AlgorithmParameterSpec params, SecureRandom random)
110: throws InvalidKeyException,
111: InvalidAlgorithmParameterException {
112: CipherParameters param;
113:
114: if (key instanceof JCEPBEKey) {
115: JCEPBEKey k = (JCEPBEKey) key;
116:
117: if (params instanceof PBEParameterSpec) {
118: param = PBE.Util.makePBEParameters(k, params,
119: wrapEngine.getAlgorithmName());
120: } else if (k.getParam() != null) {
121: param = k.getParam();
122: } else {
123: throw new InvalidAlgorithmParameterException(
124: "PBE requires PBE parameters to be set.");
125: }
126: } else {
127: param = new KeyParameter(key.getEncoded());
128: }
129:
130: if (params instanceof javax.crypto.spec.IvParameterSpec) {
131: IvParameterSpec iv = (IvParameterSpec) params;
132: param = new ParametersWithIV(param, iv.getIV());
133: }
134:
135: if (param instanceof KeyParameter && ivSize != 0) {
136: iv = new byte[ivSize];
137: random.nextBytes(iv);
138: param = new ParametersWithIV(param, iv);
139: }
140:
141: switch (opmode) {
142: case Cipher.WRAP_MODE:
143: wrapEngine.init(true, param);
144: break;
145: case Cipher.UNWRAP_MODE:
146: wrapEngine.init(false, param);
147: break;
148: case Cipher.ENCRYPT_MODE:
149: case Cipher.DECRYPT_MODE:
150: throw new IllegalArgumentException(
151: "engine only valid for wrapping");
152: default:
153: System.out.println("eeek!");
154: }
155: }
156:
157: protected void engineInit(int opmode, Key key,
158: AlgorithmParameters params, SecureRandom random)
159: throws InvalidKeyException,
160: InvalidAlgorithmParameterException {
161: AlgorithmParameterSpec paramSpec = null;
162:
163: if (params != null) {
164: for (int i = 0; i != availableSpecs.length; i++) {
165: try {
166: paramSpec = params
167: .getParameterSpec(availableSpecs[i]);
168: break;
169: } catch (Exception e) {
170: // try next spec
171: }
172: }
173:
174: if (paramSpec == null) {
175: throw new InvalidAlgorithmParameterException(
176: "can't handle parameter " + params.toString());
177: }
178: }
179:
180: engineParams = params;
181: engineInit(opmode, key, paramSpec, random);
182: }
183:
184: protected void engineInit(int opmode, Key key, SecureRandom random)
185: throws InvalidKeyException {
186: try {
187: engineInit(opmode, key, (AlgorithmParameterSpec) null,
188: random);
189: } catch (InvalidAlgorithmParameterException e) {
190: throw new IllegalArgumentException(e.getMessage());
191: }
192: }
193:
194: protected byte[] engineUpdate(byte[] input, int inputOffset,
195: int inputLen) {
196: throw new RuntimeException("not supported for wrapping");
197: }
198:
199: protected int engineUpdate(byte[] input, int inputOffset,
200: int inputLen, byte[] output, int outputOffset)
201: throws ShortBufferException {
202: throw new RuntimeException("not supported for wrapping");
203: }
204:
205: protected byte[] engineDoFinal(byte[] input, int inputOffset,
206: int inputLen) throws IllegalBlockSizeException,
207: BadPaddingException {
208: return null;
209: }
210:
211: protected int engineDoFinal(byte[] input, int inputOffset,
212: int inputLen, byte[] output, int outputOffset)
213: throws IllegalBlockSizeException, BadPaddingException {
214: return 0;
215: }
216:
217: protected byte[] engineWrap(Key key)
218: throws IllegalBlockSizeException,
219: java.security.InvalidKeyException {
220: byte[] encoded = key.getEncoded();
221: if (encoded == null) {
222: throw new InvalidKeyException(
223: "Cannot wrap key, null encoding.");
224: }
225:
226: try {
227: if (wrapEngine == null) {
228: return engineDoFinal(encoded, 0, encoded.length);
229: } else {
230: return wrapEngine.wrap(encoded, 0, encoded.length);
231: }
232: } catch (BadPaddingException e) {
233: throw new IllegalBlockSizeException(e.getMessage());
234: }
235: }
236:
237: protected Key engineUnwrap(byte[] wrappedKey,
238: String wrappedKeyAlgorithm, int wrappedKeyType)
239: throws InvalidKeyException {
240: byte[] encoded;
241: try {
242: if (wrapEngine == null) {
243: encoded = engineDoFinal(wrappedKey, 0,
244: wrappedKey.length);
245: } else {
246: encoded = wrapEngine.unwrap(wrappedKey, 0,
247: wrappedKey.length);
248: }
249: } catch (InvalidCipherTextException e) {
250: throw new InvalidKeyException(e.getMessage());
251: } catch (BadPaddingException e) {
252: throw new InvalidKeyException(e.getMessage());
253: } catch (IllegalBlockSizeException e2) {
254: throw new InvalidKeyException(e2.getMessage());
255: }
256:
257: if (wrappedKeyType == Cipher.SECRET_KEY) {
258: return new SecretKeySpec(encoded, wrappedKeyAlgorithm);
259: } else if (wrappedKeyAlgorithm.equals("")
260: && wrappedKeyType == Cipher.PRIVATE_KEY) {
261: /*
262: * The caller doesnt know the algorithm as it is part of
263: * the encrypted data.
264: */
265: ASN1InputStream bIn = new ASN1InputStream(encoded);
266: PrivateKey privKey;
267:
268: try {
269: ASN1Sequence s = (ASN1Sequence) bIn.readObject();
270: PrivateKeyInfo in = new PrivateKeyInfo(s);
271:
272: DERObjectIdentifier oid = in.getAlgorithmId()
273: .getObjectId();
274:
275: if (oid.equals(X9ObjectIdentifiers.id_ecPublicKey)) {
276: privKey = new JCEECPrivateKey(in);
277: } else if (oid
278: .equals(CryptoProObjectIdentifiers.gostR3410_94)) {
279: privKey = new JDKGOST3410PrivateKey(in);
280: } else if (oid.equals(X9ObjectIdentifiers.id_dsa)) {
281: privKey = new JDKDSAPrivateKey(in);
282: } else if (oid
283: .equals(PKCSObjectIdentifiers.dhKeyAgreement)) {
284: privKey = new JCEDHPrivateKey(in);
285: } else if (oid
286: .equals(X9ObjectIdentifiers.dhpublicnumber)) {
287: privKey = new JCEDHPrivateKey(in);
288: } else // the old standby!
289: {
290: privKey = new JCERSAPrivateCrtKey(in);
291: }
292: } catch (Exception e) {
293: throw new InvalidKeyException("Invalid key encoding.");
294: }
295:
296: return privKey;
297: } else {
298: try {
299: KeyFactory kf = KeyFactory.getInstance(
300: wrappedKeyAlgorithm, "BC");
301:
302: if (wrappedKeyType == Cipher.PUBLIC_KEY) {
303: return kf.generatePublic(new X509EncodedKeySpec(
304: encoded));
305: } else if (wrappedKeyType == Cipher.PRIVATE_KEY) {
306: return kf.generatePrivate(new PKCS8EncodedKeySpec(
307: encoded));
308: }
309: } catch (NoSuchProviderException e) {
310: throw new InvalidKeyException("Unknown key type "
311: + e.getMessage());
312: } catch (NoSuchAlgorithmException e) {
313: throw new InvalidKeyException("Unknown key type "
314: + e.getMessage());
315: } catch (InvalidKeySpecException e2) {
316: throw new InvalidKeyException("Unknown key type "
317: + e2.getMessage());
318: }
319:
320: throw new InvalidKeyException("Unknown key type "
321: + wrappedKeyType);
322: }
323: }
324:
325: //
326: // classes that inherit directly from us
327: //
328:
329: public static class DESEDEWrap extends WrapCipherSpi {
330: public DESEDEWrap() {
331: super (new DESedeWrapEngine());
332: }
333: }
334:
335: public static class RC2Wrap extends WrapCipherSpi {
336: public RC2Wrap() {
337: super (new RC2WrapEngine());
338: }
339: }
340:
341: public static class RFC3211DESedeWrap extends WrapCipherSpi {
342: public RFC3211DESedeWrap() {
343: super (new RFC3211WrapEngine(new DESedeEngine()), 8);
344: }
345: }
346: }
|