/*********************************************************** * $Id: PKCS11SignatureSpi.java 25 2006-11-30 08:17:07Z wolfgang.glas $ * * PKCS11 provider of the OpenSC project http://www.opensc-project.org * * Copyright (C) 2002-2006 ev-i Informationstechnologie GmbH * * Created: Jul 22, 2006 * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ***********************************************************/ package org.opensc.pkcs11.spi; import java.security.InvalidKeyException; import java.security.InvalidParameterException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; import java.security.SignatureException; import java.security.SignatureSpi; import org.opensc.pkcs11.PKCS11Provider; import org.opensc.pkcs11.wrap.PKCS11Exception; import org.opensc.pkcs11.wrap.PKCS11Mechanism; import org.opensc.pkcs11.wrap.PKCS11SessionChild; /** * The signature service of the OpenSC PKCS#11 provider. * * @author wglas */ public class PKCS11SignatureSpi extends SignatureSpi { PKCS11Provider provider; String algorithm; PKCS11SessionChild worker; PrivateKey privateKey; PublicKey publicKey; private native void initSignNative(long pvh, long shandle, long hsession, long hkey, int algo) throws PKCS11Exception; private native void updateSignNative(long pvh, long shandle, long hsession, byte[] data, int off, int len) throws PKCS11Exception; private native void updateSignNative1(long pvh, long shandle, long hsession, byte data) throws PKCS11Exception; private native byte[] signNative(long pvh, long shandle, long hsession) throws PKCS11Exception; private native void initVerifyNative(long pvh, long shandle, long hsession, long hkey, int algo) throws PKCS11Exception; private native void updateVerifyNative(long pvh, long shandle, long hsession, byte[] data, int off, int len) throws PKCS11Exception; private native void updateVerifyNative1(long pvh, long shandle, long hsession, byte data) throws PKCS11Exception; private native boolean verifyNative(long pvh, long shandle, long hsession, byte[] data) throws PKCS11Exception; /** * Contructs an instance of PKCS11SignatureSpi using the given provider * and algorithm. Usually, you will not have to call this contructor, * This class is implicitly instantiated using <tt>Signature.getInstance()</tt>. * * @see java.security.Signature#getInstance(java.lang.String, java.security.Provider) */ public PKCS11SignatureSpi(PKCS11Provider provider, String algorithm) { super(); this.provider = provider; this.algorithm = algorithm; } private int getPKCS11MechanismType() throws InvalidKeyException { int pkcs11_alg; if (this.algorithm.equals("NONEwithRSA")) pkcs11_alg = PKCS11Mechanism.CKM_RSA_PKCS; else if (this.algorithm.equals("MD5withRSA")) pkcs11_alg = PKCS11Mechanism.CKM_MD5_RSA_PKCS; else if (this.algorithm.equals("SHA1withRSA")) pkcs11_alg = PKCS11Mechanism.CKM_SHA1_RSA_PKCS; else if (this.algorithm.equals("SHA256withRSA")) pkcs11_alg = PKCS11Mechanism.CKM_SHA256_RSA_PKCS; else if (this.algorithm.equals("SHA384withRSA")) pkcs11_alg = PKCS11Mechanism.CKM_SHA384_RSA_PKCS; else if (this.algorithm.equals("SHA512withRSA")) pkcs11_alg = PKCS11Mechanism.CKM_SHA512_RSA_PKCS; else if (this.algorithm.equals("SHA1withDSA")) pkcs11_alg = PKCS11Mechanism.CKM_DSA_SHA1; else if (this.algorithm.equals("NONEwithDSA")) pkcs11_alg = PKCS11Mechanism.CKM_DSA; else throw new InvalidKeyException("Signature algorithm ["+ this.algorithm+"] is unsupported."); return pkcs11_alg; } /* (non-Javadoc) * @see java.security.SignatureSpi#engineInitVerify(java.security.PublicKey) */ @Override protected void engineInitVerify(PublicKey pubKey) throws InvalidKeyException { if (! (pubKey instanceof PKCS11SessionChild)) throw new InvalidKeyException("PKCS11 signature engine expects a valid PKCS11 object."); if (!this.algorithm.endsWith(pubKey.getAlgorithm())) throw new InvalidKeyException("PKCS11 key algorithm ["+ pubKey.getAlgorithm()+ "] is incompatible with signature algorithm ["+ this.algorithm+"]."); int pkcs11_alg = getPKCS11MechanismType(); this.worker = (PKCS11SessionChild)pubKey; this.publicKey = pubKey; this.privateKey = null; try { initVerifyNative(this.worker.getPvh(), this.worker.getSlotHandle(),this.worker.getSessionHandle(), this.worker.getHandle(),pkcs11_alg); } catch (PKCS11Exception e) { throw new InvalidKeyException("PKCS11 exception",e); } } /* (non-Javadoc) * @see java.security.SignatureSpi#engineInitSign(java.security.PrivateKey, java.security.SecureRandom) */ @Override protected void engineInitSign(PrivateKey privKey, SecureRandom random) throws InvalidKeyException { this.engineInitSign(privKey); } /* (non-Javadoc) * @see java.security.SignatureSpi#engineInitSign(java.security.PrivateKey) */ @Override protected void engineInitSign(PrivateKey privKey) throws InvalidKeyException { if (! (privKey instanceof PKCS11SessionChild)) throw new InvalidKeyException("PKCS11 signature engine expects a valid PKCS11 object."); if (!this.algorithm.endsWith(privKey.getAlgorithm())) throw new InvalidKeyException("PKCS11 key algorithm ["+ privKey.getAlgorithm()+ "] is incompatible with signature algorithm ["+ this.algorithm+"]."); int pkcs11_alg = getPKCS11MechanismType(); this.worker = (PKCS11SessionChild)privKey; this.publicKey = null; this.privateKey = privKey; try { initSignNative(this.worker.getPvh(), this.worker.getSlotHandle(),this.worker.getSessionHandle(), this.worker.getHandle(),pkcs11_alg); } catch (PKCS11Exception e) { throw new InvalidKeyException("PKCS11 exception",e); } } /* (non-Javadoc) * @see java.security.SignatureSpi#engineUpdate(byte) */ @Override protected void engineUpdate(byte b) throws SignatureException { if (this.worker == null) throw new SignatureException("Signature not initialized through initSign() or initVerify()."); try { if (this.privateKey != null) updateSignNative1(this.worker.getPvh(), this.worker.getSlotHandle(),this.worker.getSessionHandle(),b); else updateVerifyNative1(this.worker.getPvh(), this.worker.getSlotHandle(),this.worker.getSessionHandle(),b); } catch (PKCS11Exception e) { throw new SignatureException("PKCS11 exception",e); } } /* (non-Javadoc) * @see java.security.SignatureSpi#engineUpdate(byte[], int, int) */ @Override protected void engineUpdate(byte[] data, int off, int len) throws SignatureException { if (this.worker == null) throw new SignatureException("Signature not initialized through initSign() or initVerify()."); try { if (this.privateKey != null) updateSignNative(this.worker.getPvh(), this.worker.getSlotHandle(),this.worker.getSessionHandle(),data,off,len); else updateVerifyNative(this.worker.getPvh(), this.worker.getSlotHandle(),this.worker.getSessionHandle(),data,off,len); } catch (PKCS11Exception e) { throw new SignatureException("PKCS11 exception",e); } } /* (non-Javadoc) * @see java.security.SignatureSpi#engineSign() */ @Override protected byte[] engineSign() throws SignatureException { if (this.worker == null) throw new SignatureException("Signature not initialized through initSign() or initVerify()."); if (this.privateKey == null) throw new SignatureException("Signature not initialized through initSign()."); try { return signNative(this.worker.getPvh(), this.worker.getSlotHandle(),this.worker.getSessionHandle()); } catch (PKCS11Exception e) { throw new SignatureException("PKCS11 exception",e); } } /* (non-Javadoc) * @see java.security.SignatureSpi#engineVerify(byte[]) */ @Override protected boolean engineVerify(byte[] signature) throws SignatureException { if (this.worker == null) throw new SignatureException("Signature not initialized through initSign() or initVerify()."); if (this.publicKey == null) throw new SignatureException("Signature not initialized through initVerify()."); try { return verifyNative(this.worker.getPvh(), this.worker.getSlotHandle(),this.worker.getSessionHandle(),signature); } catch (PKCS11Exception e) { throw new SignatureException("PKCS11 exception",e); } } /* (non-Javadoc) * @see java.security.SignatureSpi#engineSetParameter(java.lang.String, java.lang.Object) */ @Override protected void engineSetParameter(String key, Object value) throws InvalidParameterException { throw new InvalidParameterException("Parameter ["+key+"] is not recognized by the PKCS11 signature engine."); } /* (non-Javadoc) * @see java.security.SignatureSpi#engineGetParameter(java.lang.String) */ @Override protected Object engineGetParameter(String key) throws InvalidParameterException { throw new InvalidParameterException("Parameter ["+key+"] is not recognized by the PKCS11 signature engine."); } }