From c99cea20257094644ed363be736a7da0014981f8 Mon Sep 17 00:00:00 2001 From: "nicolson%netscape.com" Date: Thu, 2 May 2002 20:25:15 +0000 Subject: [PATCH] New provider files for JSS 3.2. --- .../java/security/DSASignatureSpi.java | 0 .../security/GenericKeyPairGeneratorSpi.java | 0 .../security/GenericMessageDigestSpi.java | 0 .../java/security/GenericSignatureSpi.java | 0 .../java/security/JSSKeyPairGeneratorSpi.java | 100 ++++ .../provider/java/security/JSSKeyStoreSpi.c | 7 + .../java/security/JSSMessageDigestSpi.java | 138 ++++++ .../java/security/JSSSignatureSpi.java | 206 ++++++++ .../provider/java/security/KeyStoreSpi.java | 0 .../java/security/MD2MessageDigestSpi.java | 0 .../java/security/MD2RSASignatureSpi.java | 0 .../java/security/MD5MessageDigestSpi.java | 0 .../java/security/MD5RSASignatureSpi.java | 0 .../java/security/RSAKeyPairGeneratorSpi.java | 0 .../java/security/SHA1MessageDigestSpi.java | 0 .../java/security/SHA1RSASignatureSpi.java | 0 .../provider/javax/crypto/JSSCipherSpi.java | 445 ++++++++++++++++++ .../crypto/JSSJCEProvider.java} | 0 .../javax/crypto/JSSKeyGeneratorSpi.java | 133 ++++++ .../jss/provider/javax/crypto/JSSMacSpi.java | 130 +++++ .../javax/crypto/JSSSecretKeyFactorySpi.java | 296 ++++++++++++ 21 files changed, 1455 insertions(+) delete mode 100644 security/jss/org/mozilla/jss/provider/java/security/DSASignatureSpi.java delete mode 100644 security/jss/org/mozilla/jss/provider/java/security/GenericKeyPairGeneratorSpi.java delete mode 100644 security/jss/org/mozilla/jss/provider/java/security/GenericMessageDigestSpi.java delete mode 100644 security/jss/org/mozilla/jss/provider/java/security/GenericSignatureSpi.java create mode 100644 security/jss/org/mozilla/jss/provider/java/security/JSSKeyPairGeneratorSpi.java create mode 100644 security/jss/org/mozilla/jss/provider/java/security/JSSMessageDigestSpi.java create mode 100644 security/jss/org/mozilla/jss/provider/java/security/JSSSignatureSpi.java delete mode 100644 security/jss/org/mozilla/jss/provider/java/security/KeyStoreSpi.java delete mode 100644 security/jss/org/mozilla/jss/provider/java/security/MD2MessageDigestSpi.java delete mode 100644 security/jss/org/mozilla/jss/provider/java/security/MD2RSASignatureSpi.java delete mode 100644 security/jss/org/mozilla/jss/provider/java/security/MD5MessageDigestSpi.java delete mode 100644 security/jss/org/mozilla/jss/provider/java/security/MD5RSASignatureSpi.java delete mode 100644 security/jss/org/mozilla/jss/provider/java/security/RSAKeyPairGeneratorSpi.java delete mode 100644 security/jss/org/mozilla/jss/provider/java/security/SHA1MessageDigestSpi.java delete mode 100644 security/jss/org/mozilla/jss/provider/java/security/SHA1RSASignatureSpi.java create mode 100644 security/jss/org/mozilla/jss/provider/javax/crypto/JSSCipherSpi.java rename security/jss/org/mozilla/jss/provider/{java/security/DSAKeyPairGeneratorSpi.java => javax/crypto/JSSJCEProvider.java} (100%) create mode 100644 security/jss/org/mozilla/jss/provider/javax/crypto/JSSKeyGeneratorSpi.java create mode 100644 security/jss/org/mozilla/jss/provider/javax/crypto/JSSMacSpi.java create mode 100644 security/jss/org/mozilla/jss/provider/javax/crypto/JSSSecretKeyFactorySpi.java diff --git a/security/jss/org/mozilla/jss/provider/java/security/DSASignatureSpi.java b/security/jss/org/mozilla/jss/provider/java/security/DSASignatureSpi.java deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/security/jss/org/mozilla/jss/provider/java/security/GenericKeyPairGeneratorSpi.java b/security/jss/org/mozilla/jss/provider/java/security/GenericKeyPairGeneratorSpi.java deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/security/jss/org/mozilla/jss/provider/java/security/GenericMessageDigestSpi.java b/security/jss/org/mozilla/jss/provider/java/security/GenericMessageDigestSpi.java deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/security/jss/org/mozilla/jss/provider/java/security/GenericSignatureSpi.java b/security/jss/org/mozilla/jss/provider/java/security/GenericSignatureSpi.java deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/security/jss/org/mozilla/jss/provider/java/security/JSSKeyPairGeneratorSpi.java b/security/jss/org/mozilla/jss/provider/java/security/JSSKeyPairGeneratorSpi.java new file mode 100644 index 00000000000..55390417618 --- /dev/null +++ b/security/jss/org/mozilla/jss/provider/java/security/JSSKeyPairGeneratorSpi.java @@ -0,0 +1,100 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Network Security Services for Java. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2001 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +package org.mozilla.jss.provider.java.security; + +import org.mozilla.jss.crypto.*; +import java.security.KeyPair; +import java.security.SecureRandom; +import java.security.spec.AlgorithmParameterSpec; +import java.security.InvalidAlgorithmParameterException; + + +class JSSKeyPairGeneratorSpi + extends java.security.KeyPairGeneratorSpi +{ + + private KeyPairGenerator kpg; + + private JSSKeyPairGeneratorSpi() { super(); } + + protected JSSKeyPairGeneratorSpi(KeyPairAlgorithm alg) { + super(); + CryptoToken token = + TokenSupplierManager.getTokenSupplier().getThreadToken(); + try { + try { + kpg = token.getKeyPairGenerator(alg); + } catch(java.security.NoSuchAlgorithmException e) { + throw new UnsupportedOperationException( + "Token '" + token.getName() + "' does not support algorithm " + + alg.toString()); + } + } catch(TokenException e) { + throw new TokenRuntimeException(e.getMessage()); + } + } + + public void initialize(AlgorithmParameterSpec params, + SecureRandom random) throws InvalidAlgorithmParameterException + { + kpg.initialize(params, random); + } + + public void initialize(int keysize, SecureRandom random) { + kpg.initialize(keysize, random); + } + + public KeyPair generateKeyPair() { + kpg.temporaryPairs(true); + try { + return kpg.genKeyPair(); + } catch(TokenException e) { + throw new TokenRuntimeException(e.getMessage()); + } + } + + public static class RSA extends JSSKeyPairGeneratorSpi { + public RSA() { + super(KeyPairAlgorithm.RSA); + } + } + public static class DSA extends JSSKeyPairGeneratorSpi { + public DSA() { + super(KeyPairAlgorithm.DSA); + } + } +} diff --git a/security/jss/org/mozilla/jss/provider/java/security/JSSKeyStoreSpi.c b/security/jss/org/mozilla/jss/provider/java/security/JSSKeyStoreSpi.c index 82143f84c36..e7aa193c9d7 100644 --- a/security/jss/org/mozilla/jss/provider/java/security/JSSKeyStoreSpi.c +++ b/security/jss/org/mozilla/jss/provider/java/security/JSSKeyStoreSpi.c @@ -830,6 +830,12 @@ Java_org_mozilla_jss_provider_java_security_JSSKeyStoreSpi_engineSetKeyEntryNati goto finish; } +#if 1 + JSS_throwMsg(env, KEYSTORE_EXCEPTION, + "Operation is not supported. " + "http://bugzilla.mozilla.org/show_bug.cgi?id=128172"); + goto finish; +#else if( (*env)->IsInstanceOf(env, keyObj, privkClass) ) { SECKEYPrivateKey *privk; @@ -876,6 +882,7 @@ Java_org_mozilla_jss_provider_java_security_JSSKeyStoreSpi_engineSetKeyEntryNati " JSS symmetric key (PK11SymKey)"); goto finish; } +#endif finish: if( nickname != NULL ) { diff --git a/security/jss/org/mozilla/jss/provider/java/security/JSSMessageDigestSpi.java b/security/jss/org/mozilla/jss/provider/java/security/JSSMessageDigestSpi.java new file mode 100644 index 00000000000..60b89c0ee11 --- /dev/null +++ b/security/jss/org/mozilla/jss/provider/java/security/JSSMessageDigestSpi.java @@ -0,0 +1,138 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Network Security Services for Java. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +package org.mozilla.jss.provider.java.security; + +import java.security.DigestException; +import org.mozilla.jss.crypto.*; +import org.mozilla.jss.CryptoManager; +import java.security.MessageDigestSpi; + +abstract class JSSMessageDigestSpi extends MessageDigestSpi { + + private JSSMessageDigest digest; + + private JSSMessageDigestSpi() { } + + protected JSSMessageDigestSpi(DigestAlgorithm alg) { + super(); + CryptoToken token = + TokenSupplierManager.getTokenSupplier().getThreadToken(); + try { + CryptoManager cm = CryptoManager.getInstance(); + CryptoToken ikst = cm.getInternalKeyStorageToken(); + if( token.equals(ikst) ) { + // InternalKeyStorageToken doesn't support message digesting + token = cm.getInternalCryptoToken(); + } + try { + digest = token.getDigestContext(alg); + } catch(java.security.NoSuchAlgorithmException e) { + throw new UnsupportedOperationException( + "Token '" + token.getName() + "' does not support " + + "algorithm " + alg.toString()); + } + } catch(TokenException e) { + throw new TokenRuntimeException(e.getMessage()); + } catch(DigestException e1) { + throw new TokenRuntimeException(e1.getMessage()); + } catch(CryptoManager.NotInitializedException e2) { + throw new TokenRuntimeException(e2.getMessage()); + } + } + + public Object clone() throws CloneNotSupportedException { + throw new CloneNotSupportedException(); + } + + public byte[] engineDigest() { + try { + return digest.digest(); + } catch(java.security.DigestException de) { + throw new TokenRuntimeException(de.getMessage()); + } + } + + public int engineDigest(byte[] buf, int offset, int len) + throws DigestException + { + return digest.digest(buf, offset, len); + } + + public int engineGetDigestLength() { + return digest.getOutputSize(); + } + + public void engineReset() { + try { + digest.reset(); + } catch(java.security.DigestException de) { + throw new TokenRuntimeException(de.getMessage()); + } + } + + public void engineUpdate(byte input) { + try { + digest.update(input); + } catch(java.security.DigestException de) { + throw new TokenRuntimeException(de.getMessage()); + } + } + + public void engineUpdate(byte[] input, int offset, int len) { + try { + digest.update(input,offset,len); + } catch(java.security.DigestException de) { + throw new TokenRuntimeException(de.getMessage()); + } + } + + public static class SHA1 extends JSSMessageDigestSpi { + public SHA1() { + super( DigestAlgorithm.SHA1 ); + } + } + public static class MD5 extends JSSMessageDigestSpi { + public MD5() { + super( DigestAlgorithm.MD5 ); + } + } + public static class MD2 extends JSSMessageDigestSpi { + public MD2() { + super( DigestAlgorithm.MD2 ); + } + } +} diff --git a/security/jss/org/mozilla/jss/provider/java/security/JSSSignatureSpi.java b/security/jss/org/mozilla/jss/provider/java/security/JSSSignatureSpi.java new file mode 100644 index 00000000000..31973570eba --- /dev/null +++ b/security/jss/org/mozilla/jss/provider/java/security/JSSSignatureSpi.java @@ -0,0 +1,206 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Security Services for Java. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2002 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ +package org.mozilla.jss.provider.java.security; + +import java.security.SecureRandom; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.PublicKey; +import org.mozilla.jss.crypto.*; +import java.security.SignatureException; +import java.security.spec.AlgorithmParameterSpec; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidParameterException; + +class JSSSignatureSpi extends java.security.SignatureSpi { + + org.mozilla.jss.crypto.Signature sig; + SignatureAlgorithm alg; + + private JSSSignatureSpi() { } + + protected JSSSignatureSpi(SignatureAlgorithm alg) { + this.alg = alg; + } + + public Object clone() throws CloneNotSupportedException { + throw new CloneNotSupportedException(); + } + + public void engineInitSign(java.security.PrivateKey privateKey, + SecureRandom random) throws InvalidKeyException + { + // discard the random + engineInitSign(privateKey); + } + + public void engineInitSign(java.security.PrivateKey privateKey) + throws InvalidKeyException + { + try { + sig = getSigContext(privateKey); + sig.initSign((PrivateKey)privateKey); + } catch(java.security.NoSuchAlgorithmException e) { + throw new InvalidKeyException("Algorithm not supported"); + } catch(TokenException e) { + throw new InvalidKeyException("Token exception occurred"); + } + } + + private org.mozilla.jss.crypto.Signature + getSigContext(java.security.PrivateKey privateKey) + throws NoSuchAlgorithmException, InvalidKeyException, TokenException + { + CryptoToken token; + PrivateKey privk; + + System.out.println("In the brand-spanking-new getSigContext"); + + if( ! (privateKey instanceof PrivateKey) ) { + throw new InvalidKeyException(); + } + privk = (PrivateKey)privateKey; + + token = privk.getOwningToken(); + + return token.getSignatureContext(alg); + } + + public void engineInitVerify(PublicKey publicKey) + throws InvalidKeyException + { + try { + CryptoToken token = + TokenSupplierManager.getTokenSupplier().getThreadToken(); + sig = token.getSignatureContext(alg); + sig.initVerify(publicKey); + } catch(java.security.NoSuchAlgorithmException e) { + throw new InvalidKeyException("Algorithm not supported"); + } catch(TokenException e) { + throw new InvalidKeyException("Token exception occurred"); + } + } + + public void engineUpdate(byte b) + throws SignatureException + { + try { + sig.update(b); + } catch( TokenException e) { + throw new SignatureException("TokenException: "+e.toString()); + } + } + + public void engineUpdate(byte[] b, int off, int len) + throws SignatureException + { + try { + sig.update(b, off, len); + } catch( TokenException e) { + throw new SignatureException("TokenException: "+e.toString()); + } + } + + public byte[] engineSign() throws SignatureException { + try { + return sig.sign(); + } catch(TokenException e) { + throw new SignatureException("TokenException: "+e.toString()); + } + } + + public int engineSign(byte[] outbuf, int offset, int len) + throws SignatureException + { + try { + return sig.sign(outbuf, offset, len); + } catch(TokenException e) { + throw new SignatureException("TokenException: "+e.toString()); + } + } + + public boolean engineVerify(byte[] sigBytes) throws SignatureException { + try { + return sig.verify(sigBytes); + } catch( TokenException e) { + throw new SignatureException("TokenException: "+e.toString()); + } + } + + public void engineSetParameter(AlgorithmParameterSpec params) + throws InvalidAlgorithmParameterException + { + try { + sig.setParameter(params); + } catch( TokenException e ) { + throw new InvalidAlgorithmParameterException( + "TokenException: "+e.toString()); + } + } + + public Object engineGetParameter(String param) + throws InvalidParameterException + { + throw new InvalidParameterException( + "name/value parameters not supported"); + } + + public void engineSetParameter(String param, Object value) + throws InvalidParameterException + { + throw new InvalidParameterException( + "name/value parameters not supported"); + } + + public static class DSA extends JSSSignatureSpi { + public DSA() { + super(SignatureAlgorithm.DSASignatureWithSHA1Digest); + } + } + public static class MD2RSA extends JSSSignatureSpi { + public MD2RSA() { + super(SignatureAlgorithm.RSASignatureWithMD2Digest); + } + } + public static class MD5RSA extends JSSSignatureSpi { + public MD5RSA() { + super(SignatureAlgorithm.RSASignatureWithMD5Digest); + } + } + public static class SHA1RSA extends JSSSignatureSpi { + public SHA1RSA() { + super(SignatureAlgorithm.RSASignatureWithSHA1Digest); + } + } + +} diff --git a/security/jss/org/mozilla/jss/provider/java/security/KeyStoreSpi.java b/security/jss/org/mozilla/jss/provider/java/security/KeyStoreSpi.java deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/security/jss/org/mozilla/jss/provider/java/security/MD2MessageDigestSpi.java b/security/jss/org/mozilla/jss/provider/java/security/MD2MessageDigestSpi.java deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/security/jss/org/mozilla/jss/provider/java/security/MD2RSASignatureSpi.java b/security/jss/org/mozilla/jss/provider/java/security/MD2RSASignatureSpi.java deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/security/jss/org/mozilla/jss/provider/java/security/MD5MessageDigestSpi.java b/security/jss/org/mozilla/jss/provider/java/security/MD5MessageDigestSpi.java deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/security/jss/org/mozilla/jss/provider/java/security/MD5RSASignatureSpi.java b/security/jss/org/mozilla/jss/provider/java/security/MD5RSASignatureSpi.java deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/security/jss/org/mozilla/jss/provider/java/security/RSAKeyPairGeneratorSpi.java b/security/jss/org/mozilla/jss/provider/java/security/RSAKeyPairGeneratorSpi.java deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/security/jss/org/mozilla/jss/provider/java/security/SHA1MessageDigestSpi.java b/security/jss/org/mozilla/jss/provider/java/security/SHA1MessageDigestSpi.java deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/security/jss/org/mozilla/jss/provider/java/security/SHA1RSASignatureSpi.java b/security/jss/org/mozilla/jss/provider/java/security/SHA1RSASignatureSpi.java deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/security/jss/org/mozilla/jss/provider/javax/crypto/JSSCipherSpi.java b/security/jss/org/mozilla/jss/provider/javax/crypto/JSSCipherSpi.java new file mode 100644 index 00000000000..f60537a800e --- /dev/null +++ b/security/jss/org/mozilla/jss/provider/javax/crypto/JSSCipherSpi.java @@ -0,0 +1,445 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Network Security Services for Java. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +package org.mozilla.jss.provider.javax.crypto; + +import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.InvalidParameterSpecException; +import java.security.*; +import java.security.NoSuchAlgorithmException; +import javax.crypto.Cipher; +import javax.crypto.ShortBufferException; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.BadPaddingException; +import javax.crypto.spec.IvParameterSpec; +import org.mozilla.jss.crypto.KeyWrapper; +import org.mozilla.jss.crypto.KeyWrapAlgorithm; +import org.mozilla.jss.crypto.EncryptionAlgorithm; +import org.mozilla.jss.crypto.CryptoToken; +import org.mozilla.jss.crypto.TokenSupplierManager; +import org.mozilla.jss.crypto.Algorithm; +import org.mozilla.jss.crypto.SecretKeyFacade; +import org.mozilla.jss.crypto.SymmetricKey; +import org.mozilla.jss.crypto.TokenException; +import org.mozilla.jss.crypto.TokenRuntimeException; +import org.mozilla.jss.crypto.JSSSecureRandom; +import org.mozilla.jss.CryptoManager; +import org.mozilla.jss.util.Assert; +import org.mozilla.jss.pkcs11.PK11SecureRandom; + +class JSSCipherSpi extends javax.crypto.CipherSpi { + private String algFamily=null; + private String algMode=null; + private String algPadding=null; + + CryptoToken token = null; + private org.mozilla.jss.crypto.Cipher cipher=null; + private EncryptionAlgorithm encAlg = null; + private org.mozilla.jss.crypto.KeyWrapper wrapper=null; + private KeyWrapAlgorithm wrapAlg = null; + private AlgorithmParameterSpec params = null; + private int blockSize; + + private JSSCipherSpi() { } + + protected JSSCipherSpi(String algFamily) { + this.algFamily = algFamily; + token = TokenSupplierManager.getTokenSupplier().getThreadToken(); + } + + public void engineSetMode(String mode) { + this.algMode = mode; + } + + public void engineSetPadding(String padding) { + this.algPadding = padding; + } + + public void engineInit(int opmode, Key key, + AlgorithmParameterSpec givenParams, SecureRandom random) + throws InvalidKeyException, InvalidAlgorithmParameterException + { + try { + + // throw away any previous state + cipher = null; + wrapper = null; + + params = givenParams; + if( algFamily==null || algMode==null || algPadding==null) { + throw new InvalidAlgorithmParameterException( + "incorrectly specified algorithm"); + } + if( opmode != Cipher.ENCRYPT_MODE && opmode != Cipher.DECRYPT_MODE && + opmode != Cipher.WRAP_MODE && opmode != Cipher.UNWRAP_MODE ) + { + throw new InvalidKeyException("Invalid opmode"); + } + + StringBuffer buf = new StringBuffer(); + buf.append(algFamily); + buf.append('/'); + buf.append(algMode); + buf.append('/'); + buf.append(algPadding); + + if( opmode == Cipher.ENCRYPT_MODE || opmode == Cipher.DECRYPT_MODE ) { + if( ! (key instanceof SecretKeyFacade) ) { + throw new InvalidKeyException("key must be JSS key"); + } + SymmetricKey symkey = ((SecretKeyFacade)key).key; + encAlg = EncryptionAlgorithm.fromString(buf.toString()); + blockSize = encAlg.getBlockSize(); + cipher = token.getCipherContext(encAlg); + + if( opmode == Cipher.ENCRYPT_MODE ) { + if( params == noAlgParams ) { + // we're supposed to generate some params + params = generateAlgParams(encAlg, blockSize); + } + cipher.initEncrypt(symkey, params); + } else if( opmode == Cipher.DECRYPT_MODE ) { + if( params == noAlgParams) { + params = null; + } + cipher.initDecrypt(symkey, params); + } + } else { + Assert._assert( + opmode==Cipher.WRAP_MODE || opmode==Cipher.UNWRAP_MODE); + wrapAlg = KeyWrapAlgorithm.fromString(buf.toString()); + blockSize = wrapAlg.getBlockSize(); + wrapper = token.getKeyWrapper(wrapAlg); + + // generate params if necessary + if( params == noAlgParams ) { + if( opmode == Cipher.WRAP_MODE ) { + params = generateAlgParams(wrapAlg, blockSize); + } else { + Assert._assert(opmode == Cipher.UNWRAP_MODE); + params = null; + } + } + + if( key instanceof org.mozilla.jss.crypto.PrivateKey ) { + if( opmode != Cipher.UNWRAP_MODE ) { + throw new InvalidKeyException( + "Private key can only be used for unwrapping"); + } + wrapper.initUnwrap( + (org.mozilla.jss.crypto.PrivateKey) key, params ); + } else if( key instanceof PublicKey ) { + if( opmode != Cipher.WRAP_MODE ) { + throw new InvalidKeyException( + "Public key can only be used for wrapping"); + } + wrapper.initWrap((PublicKey) key, params); + } else if( key instanceof org.mozilla.jss.crypto.SecretKeyFacade) { + org.mozilla.jss.crypto.SecretKeyFacade sk = + (org.mozilla.jss.crypto.SecretKeyFacade) key; + if( opmode == Cipher.WRAP_MODE ) { + wrapper.initWrap( sk.key, params ); + } else { + Assert._assert(opmode==Cipher.UNWRAP_MODE); + wrapper.initUnwrap( sk.key, params ); + } + } else { + throw new InvalidKeyException("Invalid key type: " + + key.getClass().getName()); + } + } + } catch (NoSuchAlgorithmException e) { + throw new InvalidAlgorithmParameterException(e.getMessage()); + } catch(TokenException te) { + throw new TokenRuntimeException(te.getMessage()); + } + } + + public void engineInit(int opmode, Key key, + AlgorithmParameters givenParams, SecureRandom random) + throws InvalidKeyException, InvalidAlgorithmParameterException + { + try { + engineInit(opmode, key, givenParams.getParameterSpec(null), random); + } catch(InvalidParameterSpecException e) { + throw new InvalidAlgorithmParameterException(e.getMessage()); + } + } + + public void engineInit(int opmode, Key key, SecureRandom random) + throws InvalidKeyException + { + try { + engineInit(opmode, key, noAlgParams, random); + } catch(InvalidAlgorithmParameterException e) { + throw new InvalidKeyException(e.getMessage()); + } + } + + private static AlgorithmParameterSpec + generateAlgParams(Algorithm alg, int blockSize) throws InvalidKeyException { + Class paramClass = alg.getParameterClass(); + + if( paramClass == null ) { + // no parameters are needed + return null; + } else if( paramClass.equals( IvParameterSpec.class ) ) { + // generate an IV + byte[] iv = new byte[blockSize]; + PK11SecureRandom rng = new PK11SecureRandom(); + rng.nextBytes(iv); + return new IvParameterSpec(iv); + } else { + // I don't know any other parameter types. + throw new InvalidKeyException( + "Unable to generate parameters of type " +paramClass.getName()); + } + } + + private static class NoAlgParams implements AlgorithmParameterSpec { } + private static final NoAlgParams noAlgParams = new NoAlgParams(); + + public int engineGetBlockSize() { + return blockSize; + } + + public byte[] engineGetIV() { + if( params != null && params instanceof IvParameterSpec) { + return ((IvParameterSpec)params).getIV(); + } else { + return null; + } + } + + public AlgorithmParameters engineGetParameters() { + if( params instanceof IvParameterSpec ) { + try { + AlgorithmParameters algParams = + AlgorithmParameters.getInstance("IvAlgorithmParameters", + "Mozilla-JSS"); + algParams.init(params); + return algParams; + } catch(NoSuchAlgorithmException nsae) { + Assert.notReached(nsae.getMessage()); + } catch( NoSuchProviderException nspe) { + Assert.notReached(nspe.getMessage()); + } catch(InvalidParameterSpecException ipse) { + Assert.notReached(ipse.getMessage()); + } + } + return null; + } + + public int engineGetOutputSize(int inputLen) { + int total = (blockSize-1) + inputLen; + return ((total / blockSize) + 1) * blockSize; + } + + public byte[] engineUpdate(byte[] input, int inputOffset, int inputLen) { + if(cipher == null) { + // Cipher is supposed to catch an illegal state, so we should never + // get here + Assert.notReached(); + return null; + } + try { + return cipher.update(input, inputOffset, inputLen); + } catch(TokenException te) { + throw new TokenRuntimeException(te.getMessage()); + } + } + + public int engineUpdate(byte[] input, int inputOffset, int inputLen, + byte[] output, int outputOffset) throws ShortBufferException + { + byte[] bytes = engineUpdate(input, inputOffset, inputLen); + if( bytes.length < output.length-outputOffset ) { + throw new ShortBufferException(bytes.length + " needed, " + + (output.length-outputOffset) + " supplied"); + } + System.arraycopy(bytes, 0, output, outputOffset, bytes.length); + return bytes.length; + } + + public byte[] engineDoFinal(byte[] input, int inputOffset, int inputLen) + throws IllegalBlockSizeException, BadPaddingException + { + if( cipher == null ) { + // Cipher is supposed to catch an illegal state, so we should never + // get here + Assert.notReached(); + return null; + } + try { + return cipher.doFinal(input, inputOffset, inputLen); + } catch(IllegalStateException ise) { + Assert.notReached(); + return null; + } catch(org.mozilla.jss.crypto.IllegalBlockSizeException ibse) { + throw new IllegalBlockSizeException(ibse.getMessage()); + } catch(org.mozilla.jss.crypto.BadPaddingException bpe) { + throw new BadPaddingException(bpe.getMessage()); + } catch(TokenException te) { + throw new TokenRuntimeException(te.getMessage()); + } + } + + public int engineDoFinal(byte[] input, int inputOffset, int inputLen, + byte[] output, int outputOffset) + throws ShortBufferException, IllegalBlockSizeException, + BadPaddingException + { + byte[] bytes = engineDoFinal(input, inputOffset, inputLen); + if( bytes.length < output.length-outputOffset ) { + throw new ShortBufferException(bytes.length + " needed, " + + (output.length-outputOffset) + " supplied"); + } + System.arraycopy(bytes, 0, output, outputOffset, bytes.length); + return bytes.length; + } + + public byte[] engineWrap(Key key) + throws IllegalBlockSizeException, InvalidKeyException + { + if( wrapper == null ) { + Assert.notReached(); + return null; + } + try { + if( key instanceof org.mozilla.jss.crypto.PrivateKey ) { + return wrapper.wrap( (org.mozilla.jss.crypto.PrivateKey) key); + } else if( key instanceof org.mozilla.jss.crypto.SecretKeyFacade) { + return wrapper.wrap( + ((org.mozilla.jss.crypto.SecretKeyFacade)key).key ); + } else { + throw new InvalidKeyException("Unsupported key type: " + + key.getClass().getName()); + } + } catch(IllegalStateException ise) { + // Cipher is supposed to catch this + Assert.notReached(); + return null; + } catch(TokenException te) { + throw new TokenRuntimeException(te.getMessage()); + } + } + + public Key engineUnwrap(byte[] wrappedKey, String wrappedKeyAlgorithm, + int wrappedKeyType) + throws InvalidKeyException, NoSuchAlgorithmException + { + if( wrapper == null ) { + Assert.notReached(); + return null; + } + try { + switch(wrappedKeyType) { + case Cipher.SECRET_KEY: + return engineUnwrapSecret(wrappedKey, wrappedKeyAlgorithm); + case Cipher.PRIVATE_KEY: + return engineUnwrapPrivate(wrappedKey, wrappedKeyAlgorithm); + case Cipher.PUBLIC_KEY: + throw new UnsupportedOperationException( + "Unable to unwrap public keys"); + default: + throw new NoSuchAlgorithmException( + "Invalid key type: " + wrappedKeyType); + } + } catch(IllegalStateException ise) { + // Cipher is supposed to catch this + Assert.notReached(); + return null; + } + } + + private Key engineUnwrapSecret(byte[] wrappedKey, String wrappedKeyAlg) + throws InvalidKeyException, NoSuchAlgorithmException + { + try { + + SymmetricKey.Type wrappedKeyType = + SymmetricKey.Type.fromName( + wrappedKeyAlg.substring(0, wrappedKeyAlg.indexOf('/'))); + + // Specify 0 for key length. This will use the default key length. + // Won't work for algorithms without a default, like RC4, unless a + // padded algorithm is used. + SymmetricKey key = + wrapper.unwrapSymmetric(wrappedKey, wrappedKeyType, 0); + + return new SecretKeyFacade(key); + } catch(StringIndexOutOfBoundsException e) { + throw new NoSuchAlgorithmException("Unknown algorithm: " + + wrappedKeyAlg); + } catch(TokenException te ) { + throw new TokenRuntimeException(te.getMessage()); + } catch(InvalidAlgorithmParameterException iape ) { + throw new NoSuchAlgorithmException("Invalid algorithm parameters" + + iape.getMessage()); + } + } + + private Key engineUnwrapPrivate(byte[] wrappedKey, String wrappedKeyAlg) + throws InvalidKeyException, NoSuchAlgorithmException + { + throw new NoSuchAlgorithmException( + "Unwrapping private keys via the JCA interface is not supported: "+ + "http://bugzilla.mozilla.org/show_bug.cgi?id=135328"); + } + + static public class DES extends JSSCipherSpi { + public DES() { + super("DES"); + } + } + static public class DESede extends JSSCipherSpi { + public DESede() { + super("DESede"); + } + } + static public class AES extends JSSCipherSpi { + public AES() { + super("AES"); + } + } + static public class RC4 extends JSSCipherSpi { + public RC4() { + super("RC4"); + } + } + + +} diff --git a/security/jss/org/mozilla/jss/provider/java/security/DSAKeyPairGeneratorSpi.java b/security/jss/org/mozilla/jss/provider/javax/crypto/JSSJCEProvider.java similarity index 100% rename from security/jss/org/mozilla/jss/provider/java/security/DSAKeyPairGeneratorSpi.java rename to security/jss/org/mozilla/jss/provider/javax/crypto/JSSJCEProvider.java diff --git a/security/jss/org/mozilla/jss/provider/javax/crypto/JSSKeyGeneratorSpi.java b/security/jss/org/mozilla/jss/provider/javax/crypto/JSSKeyGeneratorSpi.java new file mode 100644 index 00000000000..5a65d92e40d --- /dev/null +++ b/security/jss/org/mozilla/jss/provider/javax/crypto/JSSKeyGeneratorSpi.java @@ -0,0 +1,133 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Network Security Services for Java. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +package org.mozilla.jss.provider.javax.crypto; + +import java.io.CharConversionException; +import java.security.*; +import java.security.spec.*; +import org.mozilla.jss.crypto.CryptoToken; +import org.mozilla.jss.crypto.KeyGenAlgorithm; +import org.mozilla.jss.crypto.TokenException; +import org.mozilla.jss.crypto.TokenRuntimeException; +import org.mozilla.jss.crypto.KeyGenerator; +import org.mozilla.jss.crypto.SymmetricKey; +import org.mozilla.jss.crypto.SecretKeyFacade; +import org.mozilla.jss.crypto.TokenSupplierManager; +import javax.crypto.*; + +class JSSKeyGeneratorSpi extends javax.crypto.KeyGeneratorSpi { + private KeyGenerator keyGenerator= null; + + private JSSKeyGeneratorSpi() {} + + protected JSSKeyGeneratorSpi(KeyGenAlgorithm alg) { + try { + CryptoToken token = + TokenSupplierManager.getTokenSupplier().getThreadToken(); + keyGenerator = token.getKeyGenerator(alg); + } catch( TokenException te) { + throw new TokenRuntimeException(te.getMessage()); + } catch(NoSuchAlgorithmException nsae) { + throw new TokenRuntimeException(nsae.getMessage()); + } + } + + protected void engineInit(int keysize, SecureRandom random) + throws InvalidParameterException + { + try { + keyGenerator.initialize(keysize); + } catch(InvalidAlgorithmParameterException e) { + throw new InvalidParameterException(e.getMessage()); + } + } + + protected void engineInit( SecureRandom random) + throws InvalidParameterException + { + // no-op. KeyGenerator.initialize isn't called if there + // are no arguments. + } + + protected void engineInit(AlgorithmParameterSpec params, + SecureRandom random) + throws InvalidAlgorithmParameterException + { + keyGenerator.initialize(params); + } + + protected SecretKey engineGenerateKey() { + try { + return new SecretKeyFacade( keyGenerator.generate() ); + } catch(IllegalStateException ise) { + throw new TokenRuntimeException( + "IllegalStateException: " + ise.getMessage()); + } catch(TokenException te) { + throw new TokenRuntimeException( te.getMessage()); + } catch(CharConversionException cce) { + throw new TokenRuntimeException( + "CharConversionException: " + cce.getMessage()); + } + } + + public static class DES extends JSSKeyGeneratorSpi { + public DES() { + super(KeyGenAlgorithm.DES); + } + } + public static class DESede extends JSSKeyGeneratorSpi { + public DESede() { + super(KeyGenAlgorithm.DESede); + } + } + public static class AES extends JSSKeyGeneratorSpi { + public AES() { + super(KeyGenAlgorithm.AES); + } + } + public static class RC4 extends JSSKeyGeneratorSpi { + public RC4() { + super(KeyGenAlgorithm.RC4); + } + } + public static class HmacSHA1 extends JSSKeyGeneratorSpi { + public HmacSHA1() { + super(KeyGenAlgorithm.PBA_SHA1_HMAC); + } + } + +} diff --git a/security/jss/org/mozilla/jss/provider/javax/crypto/JSSMacSpi.java b/security/jss/org/mozilla/jss/provider/javax/crypto/JSSMacSpi.java new file mode 100644 index 00000000000..53112c948cd --- /dev/null +++ b/security/jss/org/mozilla/jss/provider/javax/crypto/JSSMacSpi.java @@ -0,0 +1,130 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Network Security Services for Java. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +package org.mozilla.jss.provider.javax.crypto; + +import java.security.*; +import java.security.spec.*; +import org.mozilla.jss.crypto.JSSMessageDigest; +import org.mozilla.jss.crypto.CryptoToken; +import org.mozilla.jss.crypto.TokenSupplierManager; +import org.mozilla.jss.crypto.JSSMessageDigest; +import org.mozilla.jss.crypto.SecretKeyFacade; +import org.mozilla.jss.crypto.HMACAlgorithm; +import org.mozilla.jss.crypto.TokenRuntimeException; + +class JSSMacSpi extends javax.crypto.MacSpi { + + private JSSMessageDigest digest=null; + private HMACAlgorithm alg; + + private JSSMacSpi() { } + + protected JSSMacSpi(HMACAlgorithm alg) { + try { + this.alg = alg; + CryptoToken token = + TokenSupplierManager.getTokenSupplier().getThreadToken(); + digest = token.getDigestContext(alg); + } catch( DigestException de) { + throw new TokenRuntimeException(de.getMessage()); + } catch(NoSuchAlgorithmException nsae) { + throw new TokenRuntimeException(nsae.getMessage()); + } + } + + + public int engineGetMacLength() { + return alg.getOutputSize(); + } + + public void engineInit(Key key, AlgorithmParameterSpec params) + throws InvalidKeyException, InvalidAlgorithmParameterException + { + try { + if( ! (key instanceof SecretKeyFacade) ) { + throw new InvalidKeyException("Must use a JSS key"); + } + SecretKeyFacade facade = (SecretKeyFacade)key; + digest.initHMAC(facade.key); + } catch(DigestException de) { + throw new InvalidAlgorithmParameterException( + "DigestException: " + de.getMessage()); + } + } + + public void engineUpdate(byte input) { + try { + digest.update(input); + } catch(DigestException de) { + throw new TokenRuntimeException("DigestException: " + de.getMessage()); + } + } + + public void engineUpdate(byte[] input, int offset, int len) { + try { + digest.update(input, offset, len); + } catch(DigestException de) { + throw new TokenRuntimeException("DigestException: " + de.getMessage()); + } + } + + public byte[] engineDoFinal() { + try { + return digest.digest(); + } catch(DigestException de) { + throw new TokenRuntimeException("DigestException: " + de.getMessage()); + } + } + + public void engineReset() { + try { + digest.reset(); + } catch(DigestException de) { + throw new TokenRuntimeException("DigestException: " + de.getMessage()); + } + } + + public Object clone() throws CloneNotSupportedException { + throw new CloneNotSupportedException(); + } + + public static class HmacSHA1 extends JSSMacSpi { + public HmacSHA1() { + super(HMACAlgorithm.SHA1); + } + } +} diff --git a/security/jss/org/mozilla/jss/provider/javax/crypto/JSSSecretKeyFactorySpi.java b/security/jss/org/mozilla/jss/provider/javax/crypto/JSSSecretKeyFactorySpi.java new file mode 100644 index 00000000000..42d17379ba5 --- /dev/null +++ b/security/jss/org/mozilla/jss/provider/javax/crypto/JSSSecretKeyFactorySpi.java @@ -0,0 +1,296 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Network Security Services for Java. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +package org.mozilla.jss.provider.javax.crypto; + +import javax.crypto.*; +import javax.crypto.spec.*; +import java.io.CharConversionException; +import java.security.*; +import java.security.spec.*; +import org.mozilla.jss.crypto.*; +import org.mozilla.jss.CryptoManager; +import org.mozilla.jss.util.Assert; + +class JSSSecretKeyFactorySpi extends SecretKeyFactorySpi { + + private KeyGenAlgorithm alg = null; + private CryptoToken token = null; + + private JSSSecretKeyFactorySpi() { } + + protected JSSSecretKeyFactorySpi(KeyGenAlgorithm alg) { + this.alg = alg; + token = TokenSupplierManager.getTokenSupplier().getThreadToken(); + } + + private SecretKey + generateKeyFromBits(byte[] bits, SymmetricKey.Type keyType) + throws NoSuchAlgorithmException, TokenException, + InvalidKeySpecException, InvalidAlgorithmParameterException + { + try { + KeyWrapper wrapper = token.getKeyWrapper(KeyWrapAlgorithm.PLAINTEXT); + + wrapper.initUnwrap(); + + SymmetricKey symk = wrapper.unwrapSymmetric(bits, keyType, 0); + + return new SecretKeyFacade(symk); + } catch(InvalidKeyException e) { + throw new InvalidKeySpecException(e.getMessage()); + } + } + + public SecretKey + engineGenerateSecret(KeySpec spec) throws InvalidKeySpecException + { + try { + if( spec instanceof javax.crypto.spec.PBEKeySpec ) { + if( ! (spec instanceof org.mozilla.jss.crypto.PBEKeySpec) ) { + throw new InvalidKeySpecException( + "javax.crypto.spec.PBEKeySpec not supported. Use " + + "org.mozilla.jss.crypto.PBEKeySpec instead."); + } + org.mozilla.jss.crypto.PBEKeySpec kspec = + (org.mozilla.jss.crypto.PBEKeySpec) spec; + org.mozilla.jss.crypto.KeyGenerator gen =token.getKeyGenerator(alg); + PBEKeyGenParams params = kspec.getKeyGenParams(); + gen.initialize(params); + SymmetricKey symk = gen.generate(); + params.clear(); + return new SecretKeyFacade(symk); + } else if (spec instanceof DESedeKeySpec) { + if( alg != KeyGenAlgorithm.DES3 ) { + throw new InvalidKeySpecException( + "Incorrect KeySpec type (" + spec.getClass().getName() + + ") for algorithm (" + alg.toString() + ")"); + } + return generateKeyFromBits( + ((DESedeKeySpec)spec).getKey(), SymmetricKey.Type.DES3 ); + } else if (spec instanceof DESKeySpec) { + if( alg != KeyGenAlgorithm.DES ) { + throw new InvalidKeySpecException( + "Incorrect KeySpec type (" + spec.getClass().getName() + + ") for algorithm (" + alg.toString() + ")"); + } + return generateKeyFromBits( + ((DESKeySpec)spec).getKey(), SymmetricKey.Type.DES ); + } else if( spec instanceof SecretKeySpec ) { + SecretKeySpec kspec = (SecretKeySpec) spec; + SymmetricKey.Type type = + SymmetricKey.Type.fromName( kspec.getAlgorithm()); + return generateKeyFromBits( kspec.getEncoded(), type); + } else { + throw new InvalidKeySpecException( + "Unsupported KeySpec: " + spec.getClass().getName()); + } + } catch(TokenException te) { + throw new TokenRuntimeException(te.getMessage()); + } catch(InvalidAlgorithmParameterException iape) { + throw new InvalidKeySpecException( + "InvalidAlgorithmParameterException: " + iape.getMessage()); + } catch(IllegalStateException ise) { + Assert.notReached("IllegalStateException"); + throw new TokenRuntimeException("IllegalStateException: " + + ise.getMessage()); + } catch(CharConversionException cce) { + throw new InvalidKeySpecException("CharConversionException: " + + cce.getMessage()); + } catch(NoSuchAlgorithmException nsae) { + throw new InvalidKeySpecException("NoSuchAlgorithmException: " + + nsae.getMessage()); + } + } + + public KeySpec engineGetKeySpec(SecretKey key, Class keySpec) + throws InvalidKeySpecException + { + try { + if( ! (key instanceof SecretKeyFacade) ) { + throw new InvalidKeySpecException("key is not a JSS key"); + } + SymmetricKey symkey = ((SecretKeyFacade)key).key; + byte[] keyBits = symkey.getKeyData(); + SymmetricKey.Type keyType = symkey.getType(); + if( keySpec.equals(DESedeKeySpec.class) ) { + if( keyType != SymmetricKey.Type.DES3 ) { + throw new InvalidKeySpecException( + "key/spec mismatch: " + keyType + " key, DESede spec"); + } + return new DESedeKeySpec(keyBits); + } else if( keySpec.equals(DESKeySpec.class) ) { + if( keyType != SymmetricKey.Type.DES ) { + throw new InvalidKeySpecException( + "key/spec mismatch: " + keyType + " key, DES spec"); + } + return new DESKeySpec(keyBits); + } else if( keySpec.equals(SecretKeySpec.class) ) { + return new SecretKeySpec(keyBits, keyType.toString()); + } else { + throw new InvalidKeySpecException( + "Unsupported key spec: " + keySpec.getName()); + } + } catch(SymmetricKey.NotExtractableException nee) { + throw new InvalidKeySpecException("key is not extractable"); + } catch(InvalidKeyException ike) { + // This gets thrown by the key spec constructor if there's something + // wrong with the key bits. But since those key bits came from + // a real key, this should never happen. + Assert.notReached("Invalid key: " + ike.getMessage()); + throw new InvalidKeySpecException("Invalid key: " + ike.getMessage()); + } + } + + public SecretKey engineTranslateKey(SecretKey key) + throws InvalidKeyException + { + if( key instanceof SecretKeyFacade ) { + // try cloning the key + try { + SymmetricKey oldkey = ((SecretKeyFacade)key).key; + CryptoToken owningToken = oldkey.getOwningToken(); + org.mozilla.jss.crypto.KeyGenerator keygen = + token.getKeyGenerator(oldkey.getType().getKeyGenAlg()); + + SymmetricKey newkey = keygen.clone(oldkey); + + return new SecretKeyFacade(newkey); + } catch(SymmetricKey.NotExtractableException nee) { + // no way around this, we fail + throw new InvalidKeyException("key is not extractable"); + } catch(TokenException te) { + // fall through and try doing it the long way + } catch(NoSuchAlgorithmException nsae) { + throw new InvalidKeyException("Unsupported algorithm: " + + nsae.getMessage()); + } + } + + // try extracting the key value and then creating a new key + try { + byte[] keyBits = key.getEncoded(); + if( keyBits == null ) { + throw new InvalidKeyException("Key is not extractable"); + } + SymmetricKey.Type keyType = + SymmetricKey.Type.fromName( key.getAlgorithm() ); + return generateKeyFromBits( keyBits, keyType); + } catch( NoSuchAlgorithmException nsae ) { + throw new InvalidKeyException("Unsupported algorithm: " + + key.getAlgorithm()); + } catch(TokenException te) { + throw new InvalidKeyException("Token failed to process key: " + + te.getMessage()); + } catch(InvalidKeySpecException ikse) { + throw new InvalidKeyException("Invalid key spec: " + + ikse.getMessage()); + } catch(InvalidAlgorithmParameterException iape) { + throw new InvalidKeyException("Invalid algorithm parameters: " + + iape.getMessage()); + } + } + + public static void main(String args[]) { + + try { + CryptoManager.initialize("."); + + CryptoManager cm = CryptoManager.getInstance(); + CryptoToken tok = cm.getInternalCryptoToken(); + cm.setThreadToken(tok); + + org.mozilla.jss.crypto.KeyGenerator keygen = + tok.getKeyGenerator(KeyGenAlgorithm.DES3); + + SymmetricKey symk = keygen.generate(); + SecretKeyFacade origKey = new SecretKeyFacade(symk); + + JSSSecretKeyFactorySpi fact = + new JSSSecretKeyFactorySpi(KeyGenAlgorithm.DES3); + + DESedeKeySpec kspec = (DESedeKeySpec) + fact.engineGetKeySpec(origKey, DESedeKeySpec.class); + + SecretKeyFacade newKey = (SecretKeyFacade) + fact.engineGenerateSecret(kspec); + + org.mozilla.jss.crypto.Cipher cipher = + tok.getCipherContext(EncryptionAlgorithm.DES3_ECB); + cipher.initEncrypt(origKey.key); + byte[] cipherText = cipher.doFinal( + "Hello, World!!!!".getBytes("UTF-8") ); + System.out.println("ciphertext is " + cipherText.length + " bytes"); + + cipher.initDecrypt(newKey.key); + byte[] plainText = cipher.doFinal(cipherText); + System.out.println("recovered plaintext is " + plainText.length + + " bytes"); + + String recovered = new String(plainText, "UTF-8"); + System.out.println("Recovered '" + recovered + "'"); + + } catch(Throwable t) { + t.printStackTrace(); + } + } + + public static class DES extends JSSSecretKeyFactorySpi { + public DES() { + super(KeyGenAlgorithm.DES); + } + } + public static class DESede extends JSSSecretKeyFactorySpi { + public DESede() { + super(KeyGenAlgorithm.DESede); + } + } + public static class AES extends JSSSecretKeyFactorySpi { + public AES() { + super(KeyGenAlgorithm.AES); + } + } + public static class RC4 extends JSSSecretKeyFactorySpi { + public RC4() { + super(KeyGenAlgorithm.RC4); + } + } + public static class HmacSHA1 extends JSSSecretKeyFactorySpi { + public HmacSHA1() { + super(KeyGenAlgorithm.PBA_SHA1_HMAC); + } + } +}