/*********************************************************** * $Id$ * * PKCS11 provider of the OpenSC project http://www.opensc-project.org * * Copyright (C) 2002-2006 ev-i Informationstechnologie GmbH * * Created: Jul 19, 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.wrap; import javax.security.auth.DestroyFailedException; import org.opensc.util.DestroyableHolder; import org.opensc.util.Util; /** * @author wglas * * This class represents an open session on a token. */ public class PKCS11Session extends DestroyableHolder { /** * The C handle of the provider. */ protected long pvh; /** * The C handle of the slot. */ protected long shandle; /** * The C handle of the session. */ protected long handle; private boolean userLoggedIn; private boolean SOLoggedIn; public static final int OPEN_MODE_READ_ONLY = 0; public static final int OPEN_MODE_READ_WRITE = 1; /** * The counterpart of SKU_SO in pkcs11t.h, used to present the * security officer PIN to the card. */ private static int LOGIN_TYPE_SO = 0; /** * The counterpart of SKU_USER in pkcs11t.h, used to present the * user PIN to the card. */ private static int LOGIN_TYPE_USER = 1; /** * Contruct a session from a given handle- */ protected PKCS11Session(PKCS11Slot slot, long handle) { super(slot); this.pvh = slot.getPvh(); this.shandle = slot.getHandle(); this.handle = handle; this.userLoggedIn = false; this.SOLoggedIn = false; } private static native long openNative(long pvh, long shandle, int mode) throws PKCS11Exception; private static native void closeNative(long pvh, long shandle, long handle); private static native void signInitNative(long pvh, long shandle, long hsession, long hkey, int mech, byte[] param) throws PKCS11Exception; private static native void signUpdateNative(long pvh, long shandle, long hsession, byte[] data, int off, int len) throws PKCS11Exception; private static native void signUpdateByteNative(long pvh, long shandle, long hsession, byte data) throws PKCS11Exception; private static native byte[] signFinalNative(long pvh, long shandle, long hsession) throws PKCS11Exception; private static native byte[] signNative(long pvh, long shandle, long hsession, byte[] data, int off, int len) throws PKCS11Exception; private static native void verifyInitNative(long pvh, long shandle, long hsession, long hkey, int mech, byte[] param) throws PKCS11Exception; private static native void verifyUpdateNative(long pvh, long shandle, long hsession, byte[] data, int off, int len) throws PKCS11Exception; private static native void verifyUpdateByteNative(long pvh, long shandle, long hsession, byte data) throws PKCS11Exception; private static native boolean verifyFinalNative(long pvh, long shandle, long hsession, byte[] signature) throws PKCS11Exception; private static native boolean verifyNative(long pvh, long shandle, long hsession, byte[] data, int off, int len, byte[] signature) throws PKCS11Exception; private static native void encryptInitNative(long pvh, long shandle, long hsession, long hkey, int pkcs11_alg, byte[] param) throws PKCS11Exception; private static native byte[] encryptUpdateNative(long pvh, long shandle, long hsession, byte[] data, int off, int len) throws PKCS11Exception; private static native int encryptUpdateOffNative(long pvh, long shandle, long hsession, byte[] input, int off, int len, byte[] output, int output_off) throws PKCS11Exception; private static native byte[] encryptFinalNative(long pvh, long shandle, long hsession) throws PKCS11Exception; private static native byte[] encryptNative(long pvh, long shandle, long hsession, byte[] data, int off, int len) throws PKCS11Exception; private static native void decryptInitNative(long pvh, long shandle, long hsession, long hkey, int pkcs11_alg, byte[] param) throws PKCS11Exception; private static native byte[] decryptUpdateNative(long pvh, long shandle, long hsession, byte[] data, int off, int len) throws PKCS11Exception; private static native int decryptUpdateOffNative(long pvh, long shandle, long hsession, byte[] input, int off, int len, byte[] output, int output_off) throws PKCS11Exception; private static native byte[] decryptFinalNative(long pvh, long shandle, long hsession) throws PKCS11Exception; private static native byte[] decryptNative(long pvh, long shandle, long hsession, byte[] data, int off, int len) throws PKCS11Exception; /** * Opens a session on the given slot. * * @param slot The slot on which we open the session. * @param mode Either OPEN_MODE_READ_ONLY or OPEN_MODE_READ_WRITE * @return The open session. * @throws PKCS11Exception Upon errors of the underlying PKCS#11 module. */ public static PKCS11Session open(PKCS11Slot slot, int mode) throws PKCS11Exception { long handle = openNative(slot.getPvh(),slot.getHandle(),mode); return new PKCS11Session(slot,handle); } private native void loginNative(long _pvh, long _shandle, long _handle, int type, byte[] pin) throws PKCS11Exception; /** * Presents the user PIN to the token. Should only be called after open(). * * @param pin The user pin. This paremeter may be <code>null</code>, if the * token has a protected authentication path. * * @throws PKCS11Exception Upon errors of the underlying PKCS#11 engine. * * @see PKCS11Slot#hasTokenProtectedAuthPath() */ public void loginUser(char[] pin) throws PKCS11Exception { if (this.userLoggedIn) throw new PKCS11Exception("The user is already logged in."); loginNative(this.pvh,this.shandle,this.handle,LOGIN_TYPE_USER,Util.translatePin(pin)); this.userLoggedIn = true; } /** * Presents the security officer PIN to the token. Should only be called after open(). * * @param pin The SO pin. This paremeter may be <code>null</code>, if the * token has a protected authentication path. * * @throws PKCS11Exception Upon errors of the underlying PKCS#11 engine. * * @see PKCS11Slot#hasTokenProtectedAuthPath() */ public void loginSO(char[] pin) throws PKCS11Exception { if (this.SOLoggedIn) throw new PKCS11Exception("The security officer is already logged in."); loginNative(this.pvh,this.shandle,this.handle,LOGIN_TYPE_SO,Util.translatePin(pin)); this.SOLoggedIn = true; } /** * @return Returns, whether the security officer has successfully logged in * through loginSO(). */ public boolean isSOLoggedIn() { return this.SOLoggedIn; } /** * @return Returns, whether the user has successfully logged in * through loginUser(). */ public boolean isUserLoggedIn() { return this.userLoggedIn; } private native void logoutNative(long _pvh, long _shandle, long _handle) throws PKCS11Exception; /** * Logs out from the token. */ public void logout() throws PKCS11Exception { if (!this.userLoggedIn && ! this.SOLoggedIn) return; logoutNative(this.pvh,this.shandle,this.handle); this.userLoggedIn = false; this.SOLoggedIn = false; } /* (non-Javadoc) * @see org.opensc.util.DestroyableChild#destroy() */ @Override public void destroy() throws DestroyFailedException { closeNative(this.pvh,this.shandle,this.handle); this.handle = 0; this.shandle = 0; this.pvh = 0; this.userLoggedIn = false; this.SOLoggedIn = false; super.destroy(); } /** * @return Returns the C handle of the underlying provider. */ protected long getPvh() { return this.pvh; } /** * @return Returns the C handle of the slot. */ protected long getSlotHandle() { return this.shandle; } /** * @return Returns the C handle of the session. */ protected long getHandle() { return this.handle; } /** * Initialize signing operation (C_SignInit) * * @param key PKCS#11 key handle * @param mech CKM_ mechanism * @param param Parameter for mechanims as plain byte array in machine dependent structure * @throws PKCS11Exception */ public void signInit(int key, int mech, byte[] param) throws PKCS11Exception { signInitNative(this.pvh, this.shandle, this.handle, (long)key, mech, param); } /** * Initialize signing operation (C_SignInit) * * @param key PKCS#11 object representing a key * @param mech CKM_ mechanism * @param param Parameter for mechanims as plain byte array in machine dependent structure * @throws PKCS11Exception */ public void signInit(PKCS11Object key, int mech, byte[] param) throws PKCS11Exception { signInitNative(this.pvh, this.shandle, this.handle, key.getHandle(), mech, param); } /** * Update internal signing buffer (C_SignUpdate) * * @param data Partial data to be signed * @param off Offset in data buffer * @param len Length of data in buffer * @throws PKCS11Exception */ public void signUpdate(byte[] data, int off, int len) throws PKCS11Exception { signUpdateNative(this.pvh, this.shandle, this.handle, data, off, len); } /** * Update internal signing buffer with single byte (C_SignUpdate) * * @param data Byte to add * @throws PKCS11Exception */ public void signUpdate(byte data) throws PKCS11Exception { signUpdateByteNative(this.pvh, this.shandle, this.handle, data); } /** * End signing operation and generate signature (C_SignFinal) * @return Signature * @throws PKCS11Exception */ public byte[] signFinal() throws PKCS11Exception { return signFinalNative(this.pvh, this.shandle, this.handle); } /** * Single step signing operation (C_Sign) * * @param data Data to be signed * @param off Offset in data buffer * @param len Length of data in buffer, starting at offset * @return Signature * @throws PKCS11Exception */ public byte[] sign(byte[] data, int off, int len) throws PKCS11Exception { return signNative(this.pvh, this.shandle, this.handle, data, off, len); } /** * Single step signing operation (C_Sign) * * @param data Data to be signed * @return Signature * @throws PKCS11Exception */ public byte[] sign(byte[] data) throws PKCS11Exception { return sign(data, 0, data.length); } /** * Initialize verifying operation (C_VerifyInit) * * @param key PKCS#11 key handle * @param mech CKM_ mechanism * @param param Parameter for mechanims as plain byte array in machine dependent structure * @throws PKCS11Exception */ public void verifyInit(int key, int mech, byte[] param) throws PKCS11Exception { verifyInitNative(this.pvh, this.shandle, this.handle, (long)key, mech, param); } /** * Initialize verifying operation (C_VerifyInit) * * @param key PKCS#11 object representing a key * @param mech CKM_ mechanism * @param param Parameter for mechanims as plain byte array in machine dependent structure * @throws PKCS11Exception */ public void verifyInit(PKCS11Object key, int mech, byte[] param) throws PKCS11Exception { verifyInitNative(this.pvh, this.shandle, this.handle, key.getHandle(), mech, param); } /** * Update internal verifying buffer (C_VerifyUpdate) * * @param data Partial data to be signed * @param off Offset in data buffer * @param len Length of data in buffer * @throws PKCS11Exception */ public void verifyUpdate(byte[] data, int off, int len) throws PKCS11Exception { verifyUpdateNative(this.pvh, this.shandle, this.handle, data, off, len); } /** * Update internal verifying buffer with single byte (C_VerifyUpdate) * * @param data Byte to add * @throws PKCS11Exception */ public void verifyUpdate(byte data) throws PKCS11Exception { verifyUpdateByteNative(this.pvh, this.shandle, this.handle, data); } /** * End verifying operation and validate signature (C_VerifyFinal) * @param signature Signature to be verified * @return True if signature is valid * @throws PKCS11Exception */ public boolean verifyFinal(byte[] signature) throws PKCS11Exception { return verifyFinalNative(this.pvh, this.shandle, this.handle, signature); } /** * Single step verifying operation (C_Verify) * * @param data Data to be verified * @param off Offset in data buffer * @param len Length of data in buffer, starting at offset * @param signature Signature to be verified * @return True if signature is valid * @throws PKCS11Exception */ public boolean verify(byte[] data, int off, int len, byte[] signature) throws PKCS11Exception { return verifyNative(this.pvh, this.shandle, this.handle, data, off, len, signature); } /** * Single step verifying operation (C_Verify) * * @param data Message to be verified * @param signature Signature to be verified * @return true if the signature is valid * @throws PKCS11Exception */ public boolean verify(byte[] data, byte[] signature) throws PKCS11Exception { return verify(data, 0, data.length, signature); } /** * Initialize encryption operation (C_EncryptInit) * * @param key PKCS#11 key handle * @param mech CKM_ mechanism * @param param Parameter for mechanims as plain byte array in machine dependent structure * @throws PKCS11Exception */ public void encryptInit(int key, int mech, byte[] param) throws PKCS11Exception { encryptInitNative(this.pvh, this.shandle, this.handle, (long)key, mech, param); } /** * Initialize encryption operation (C_EncryptInit) * * @param key PKCS#11 object representing a key * @param mech CKM_ mechanism * @param param Parameter for mechanims as plain byte array in machine dependent structure * @throws PKCS11Exception */ public void encryptInit(PKCS11Object key, int mech, byte[] param) throws PKCS11Exception { encryptInitNative(this.pvh, this.shandle, this.handle, key.getHandle(), mech, param); } /** * Process next block in encryption operation (C_EncryptUpdate) * * @param data Data to encrypt * @param off Offset in data * @param len Length of region from offset * @return Encrypted data * @throws PKCS11Exception */ public byte[] encryptUpdate(byte[] data, int off, int len) throws PKCS11Exception { return encryptUpdateNative(this.pvh, this.shandle, this.handle, data, off, len); } /** * Process next block in encryption operation (C_EncryptUpdate) * * @param input Data to encrypt * @param off Offset in data * @param len Length of region from offset * @param output Output buffer * @param output_off Offset in output buffer * @return Length of data in output * @throws PKCS11Exception */ public int encryptUpdateOff(byte[] input, int off, int len, byte[] output, int output_off) throws PKCS11Exception { return encryptUpdateOffNative(this.pvh, this.shandle, this.handle, input, off, len, output, output_off); } /** * Perform final encryption step (C_EncryptFinal) * * @return Final encrypted block or null if none * @throws PKCS11Exception */ public byte[] encryptFinal() throws PKCS11Exception { return encryptFinalNative(this.pvh, this.shandle, this.handle); } /** * Single step encryption operation (C_Encrypt) * * @param data Data to encrypt * @param off Offset in data * @param len Length of region from offset * @return Encrypted data * @throws PKCS11Exception */ public byte[] encrypt(byte[] data, int off, int len) throws PKCS11Exception { return encryptNative(this.pvh, this.shandle, this.handle, data, off, len); } /** * Initialize decryption operation (C_DecryptInit) * * @param key PKCS#11 key handle * @param mech CKM_ mechanism * @param param Parameter for mechanims as plain byte array in machine dependent structure * @throws PKCS11Exception */ public void decryptInit(int key, int mech, byte[] param) throws PKCS11Exception { decryptInitNative(this.pvh, this.shandle, this.handle, (long)key, mech, param); } /** * Initialize decryption operation (C_DecryptInit) * * @param key PKCS#11 object representing a key * @param mech CKM_ mechanism * @param param Parameter for mechanims as plain byte array in machine dependent structure * @throws PKCS11Exception */ public void decryptInit(PKCS11Object key, int mech, byte[] param) throws PKCS11Exception { decryptInitNative(this.pvh, this.shandle, this.handle, key.getHandle(), mech, param); } /** * Process next block in decryption operation (C_DecryptUpdate) * * @param data Data to decrypt * @param off Offset in data * @param len Length of region from offset * @return Decrypted data * @throws PKCS11Exception */ public byte[] decryptUpdate(byte[] data, int off, int len) throws PKCS11Exception { return decryptUpdateNative(this.pvh, this.shandle, this.handle, data, off, len); } /** * Process next block in decryption operation (C_DecryptUpdate) * * @param input Data to decrypt * @param off Offset in data * @param len Length of region from offset * @param output Output buffer * @param output_off Offset in output buffer * @return Length of data in output * @throws PKCS11Exception */ public int decryptUpdateOff(byte[] input, int off, int len, byte[] output, int output_off) throws PKCS11Exception { return decryptUpdateOffNative(this.pvh, this.shandle, this.handle, input, off, len, output, output_off); } /** * Perform final decryption step (C_DecryptFinal) * * @return Final decrypted block or null if none * @throws PKCS11Exception */ public byte[] decryptFinal() throws PKCS11Exception { return decryptFinalNative(this.pvh, this.shandle, this.handle); } /** * Single step decryption operation (C_Decrypt) * * @param data Data to decrypt * @param off Offset in data * @param len Length of region from offset * @return Decrypted data * @throws PKCS11Exception */ public byte[] decrypt(byte[] data, int off, int len) throws PKCS11Exception { return decryptNative(this.pvh, this.shandle, this.handle, data, off, len); } }