All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.xipki.pkcs11.wrapper.Session Maven / Gradle / Ivy

// Copyright (c) 2002 Graz University of Technology. All rights reserved.
// License IAIK PKCS#11 Wrapper License.
//
// Copyright (c) 2022 xipki. All rights reserved.
// License Apache License 2.0

package org.xipki.pkcs11.wrapper;

import iaik.pkcs.pkcs11.wrapper.*;
import org.xipki.pkcs11.wrapper.attrs.*;
import org.xipki.pkcs11.wrapper.params.*;

import java.security.PublicKey;
import java.security.interfaces.ECPublicKey;
import java.security.spec.ECPoint;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

import static org.xipki.pkcs11.wrapper.PKCS11Constants.*;

/**
 * Session objects are used to perform cryptographic operations on a token. The application gets a
 * Session object by calling openSession on a certain Token object. Having the session object, the
 * application may login the user, if required.
 *
 * 
 * 
 *   TokenInfo tokenInfo = token.getTokenInfo();
 *   // check, if log-in of the user is required at all
 *   if (tokenInfo.isLoginRequired()) {
 *     // check, if the token has own means to authenticate the user; e.g. a PIN-pad on the reader
 *     if (tokenInfo.isProtectedAuthenticationPath()) {
 *       System.out.println("Please enter the user PIN at the PIN-pad of your reader.");
 *       session.login(CKU_USER, null); // the token prompts the PIN by other means; e.g. PIN-pad
 *     } else {
 *       System.out.print("Enter user-PIN and press [return key]: ");
 *       System.out.flush();
 *       BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
 *       String userPINString = input.readLine();
 *       session.login(CKU_USER, userPINString.toCharArray());
 *     }
 *   }
 * 
 * 
* * If the application does not need the session any longer, it should close the * session. * *
 * 
 *   session.closeSession();
 * 
 * 
* * @author Karl Scheibelhofer (SIC) * @author Lijun Liao (xipki) */ public class Session { private static final int SIGN_TYPE_ECDSA = 1; private static final int SIGN_TYPE_SM2 = 2; /** * A reference to the underlying PKCS#11 module to perform the operations. */ private final PKCS11Module module; /** * A reference to the underlying PKCS#11 module to perform the operations. */ private final PKCS11 pkcs11; /** * The session handle to perform the operations with. */ private long sessionHandle; /** * The token to perform the operations on. */ protected final Token token; /** * True, if UTF8 encoding is used as character encoding for character array attributes and PINs. */ private final boolean useUtf8; /** * True, if this is an R/W session. */ private Boolean rwSession = null; private int signatureType; private long signOrVerifyKeyHandle; private ExtraParams signVerifyExtraParams; /** * Constructor taking the token and the session handle. * * @param token The token this session operates with. * @param sessionHandle The session handle to perform the operations with. */ protected Session(Token token, long sessionHandle) { this.token = Functions.requireNonNull("token", token); this.module = token.getSlot().getModule(); this.pkcs11 = module.getPKCS11Module(); this.sessionHandle = sessionHandle; this.useUtf8 = token.isUseUtf8Encoding(); } /** * Initializes the user-PIN. Can only be called from a read-write security officer session. May be * used to set a new user-PIN if the user-PIN is locked. * * @param pin The new user-PIN. This parameter may be null, if the token has a protected * authentication path. Refer to the PKCS#11 standard for details. * @throws PKCS11Exception If the session has not the right to set the PIN of if the operation fails for some * other reason. */ public void initPIN(char[] pin) throws PKCS11Exception { final String method = "C_InitPIN"; debugIn(method); try { pkcs11.C_InitPIN(sessionHandle, pin, useUtf8); debugOut(method); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * Set the user-PIN to a new value. Can only be called from a read-write sessions. * * @param oldPin The old (current) user-PIN. * @param newPin The new value for the user-PIN. * @throws PKCS11Exception If setting the new PIN fails. */ public void setPIN(char[] oldPin, char[] newPin) throws PKCS11Exception { final String method = "C_SetPIN"; debugIn(method); try { pkcs11.C_SetPIN(sessionHandle, oldPin, newPin, useUtf8); debugOut(method); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * Closes this session. * * @throws PKCS11Exception If closing the session failed. */ public void closeSession() throws PKCS11Exception { final String method = "C_CloseSession"; debugIn(method); try { pkcs11.C_CloseSession(sessionHandle); debugOut(method); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * Get the handle of this session. * * @return The handle of this session. */ public long getSessionHandle() { return sessionHandle; } /** * Get information about this session. * * @return An object providing information about this session. * @throws PKCS11Exception If getting the information failed. */ public SessionInfo getSessionInfo() throws PKCS11Exception { try { return new SessionInfo(pkcs11.C_GetSessionInfo(sessionHandle)); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { throw module.convertException(e); } } /** * terminates active session based operations. * * @throws PKCS11Exception If terminating operations failed */ public void sessionCancel() throws PKCS11Exception { final String method = "C_SessionCancel"; long flags = 0L; //Add Flags? debugIn(method); try { pkcs11.C_SessionCancel(sessionHandle, flags); debugOut(method); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * Get the Module which this Session object operates with. * * @return The module of this session. */ public PKCS11Module getModule() { return module; } /** * Get the token that created this Session object. * * @return The token of this session. */ public Token getToken() { return token; } /** * Get the current operation state. This state can be used later to restore the operation to * exactly this state. * * @return The current operation state as a byte array. * @throws PKCS11Exception If saving the state fails or is not possible. */ public byte[] getOperationState() throws PKCS11Exception { try { return pkcs11.C_GetOperationState(sessionHandle); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { throw module.convertException(e); } } /** * Sets the operation state of this session to a previously saved one. This method may need the * key used during the saved operation to continue, because it may not be possible to save a key * into the state's byte array. Refer to the PKCS#11 standard for details on this function. * * @param operationState The previously saved state as returned by getOperationState(). * @param encryptionKeyHandle An encryption or decryption key handle, if an encryption or * decryption operation was saved which should be continued, but * the keys could not be saved. * @param authenticationKeyHandle A signing, verification of MAC key handle, if a signing, * verification or MAC operation needs to be restored that could * not save the key. * @throws PKCS11Exception If restoring the state fails. */ public void setOperationState(byte[] operationState, long encryptionKeyHandle, long authenticationKeyHandle) throws PKCS11Exception { try { pkcs11.C_SetOperationState(sessionHandle, operationState, encryptionKeyHandle, authenticationKeyHandle); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { throw module.convertException(e); } } public void setSessionHandle(long sessionHandle) { this.sessionHandle = sessionHandle; } /** * Returns whether UTF8 encoding is set. * * @return true, if UTF8 is used as character encoding for character array attributes and PINs. */ public boolean isSetUtf8Encoding() { return useUtf8; } /** * Logs in the user or the security officer to the session. Notice that all sessions of a token * have the same login state; i.e. if you login the user to one session all other open sessions of * this token get user rights. * * @param userType CKU_SO for the security officer or CKU_USER to login the user. * @param pin The PIN. The security officer-PIN or the user-PIN depending on the userType parameter. * @throws PKCS11Exception If login fails. */ public void login(long userType, char[] pin) throws PKCS11Exception { final String method = "C_Login"; if (StaticLogger.isDebugEnabled()) { debugIn(method, "userType={}", codeToName(Category.CKU, userType)); } try { pkcs11.C_Login(sessionHandle, userType, pin, useUtf8); debugOut(method); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * Logs in the user or the security officer to the session. Notice that all sessions of a token * have the same login state; i.e. if you log in the user to one session all other open sessions of * this token get user rights. * * @param userType CKU_SO for the security officer or CKU_USER to log in the user. * @param pin The PIN. The security officer-PIN or the user-PIN depending on the userType parameter. * @param username The username of the user. * @throws PKCS11Exception If login fails. */ public void loginUser(long userType, char[] pin, char[] username) throws PKCS11Exception { final String method = "C_LoginUser"; if (StaticLogger.isDebugEnabled()) { debugIn(method, "userType={}, username={}", codeToName(Category.CKU, userType), (username == null) ? null : new String(username)); } try { pkcs11.C_LoginUser(sessionHandle, userType, pin, username, useUtf8); debugOut(method); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * Logs out this session. * * @throws PKCS11Exception If logging out the session fails. */ public void logout() throws PKCS11Exception { final String method = "C_Logout"; debugIn(method); try { pkcs11.C_Logout(sessionHandle); debugOut(method); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * Create a new object on the token (or in the session). The application must provide a template * that holds enough information to create a certain object. For instance, if the application * wants to create a new DES key object it creates a new instance of the AttributesTemplate class to * serve as a template. The application must set all attributes of this new object which are * required for the creation of such an object on the token. Then it passes this DESSecretKey * object to this method to create the object on the token. Example: * AttributesTemplate desKeyTemplate = AttributesTemplate.newSecretKey(CKK_DES3); * // the key type is set by the DESSecretKey's constructor, so you need not do it * desKeyTemplate.value(myDesKeyValueAs8BytesLongByteArray) * .token(true) * .private(true); * .encrypt(true); * .decrypt(true); * ... * long theCreatedDESKeyObjectHandle = userSession.createObject(desKeyTemplate); * Refer to the PKCS#11 standard to find out what attributes must be set for certain types * of objects to create them on the token. * * @param template The template object that holds all values that the new object on the token should * contain. * @return A new PKCS#11 Object that serves holds all the * (readable) attributes of the object on the token. In contrast to the templateObject, * this object might have certain attributes set to token-dependent default-values. * @throws PKCS11Exception If the creation of the new object fails. If it fails, the no new object was * created on the token. */ public long createObject(AttributeVector template) throws PKCS11Exception { final String method = "C_CreateObject"; if (StaticLogger.isDebugEnabled()) { long objClass = template.class_(); if (objClass == CKO_PRIVATE_KEY || objClass == CKO_SECRET_KEY) { AttributeVector logTemplate = template.copyWithoutByteArrayAttributes(); logTemplate.id(template.id()) .modulus(template.modulus()).publicExponent(template.publicExponent()) // RSA .ecParams(template.ecParams()).ecPoint(template.ecPoint()) // EC .prime(template.prime()).subprime(template.subprime()).base(template.base()); // DSA debugIn(method, "part of template={}", logTemplate); } else { debugIn(method, "template={}", template); } } try { long hObject = pkcs11.C_CreateObject(sessionHandle, toOutCKAttributes(template), useUtf8); debugOut(method, "hObject={}", hObject); traceObject("created object", hObject); return hObject; } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } public long createPrivateKeyObject(AttributeVector template, PublicKey publicKey) throws PKCS11Exception { if (publicKey instanceof ECPublicKey && privateKeyWithEcPoint(template.keyType())) { byte[] ecParams = template.ecParams(); Integer fieldSize = Functions.getECFieldSize(ecParams); ECPoint w = ((ECPublicKey) publicKey).getW(); byte[] wx = Functions.asUnsignedByteArray(w.getAffineX()); byte[] wy = Functions.asUnsignedByteArray(w.getAffineY()); if (fieldSize == null) { fieldSize = Math.max(wx.length, wy.length); } else { if (wx.length > fieldSize || wy.length > fieldSize) { throw new IllegalStateException("should not happen, public key and ecParams do not match"); } } byte[] ecPoint = new byte[1 + 2 * fieldSize]; ecPoint[0] = 4; System.arraycopy(wx, 0, ecPoint, 1 + fieldSize - wx.length, wx.length); System.arraycopy(wy, 0, ecPoint, ecPoint.length - wy.length, wy.length); template.ecPoint(ecPoint); } return createObject(template); } /** * Create EC private key object in the PKCS#11 device. * @param template Template of the EC private key. * @param ecPoint The encoded EC-Point. May be null. * @return object handle of the new EC private key. * @throws PKCS11Exception If creating the object fails for some reason. */ public long createECPrivateKeyObject(AttributeVector template, byte[] ecPoint) throws PKCS11Exception { if (ecPoint != null && privateKeyWithEcPoint(template.keyType())) { template.ecPoint(ecPoint); } return createObject(template); } private boolean privateKeyWithEcPoint(Long keyType) { if (keyType == null) { return false; } if (CKK_EC == keyType) { return module.hasVendorBehaviour(PKCS11Module.BEHAVIOUR_EC_PRIVATEKEY_ECPOINT); } else if (CKK_VENDOR_SM2 == keyType) { return module.hasVendorBehaviour(PKCS11Module.BEHAVIOUR_SM2_PRIVATEKEY_ECPOINT); } else { return false; } } /** * Copy an existing object. The source object and a template object are given. Any value set in * the template object will override the corresponding value from the source object, when the new * object is created. See the PKCS#11 standard for details. * * @param sourceObjectHandle The source object of the copy operation. * @param template A template object whose attribute values are used for the new object; i.e. they have * higher priority than the attribute values from the source object. May be null; in that * case the new object is just a one-to-one copy of the sourceObject. * @return The new object that is created by copying the source object and setting attributes to * the values given by the template. * @throws PKCS11Exception If copying the object fails for some reason. */ public long copyObject(long sourceObjectHandle, AttributeVector template) throws PKCS11Exception { final String method = "C_CopyObject"; debugIn(method, "sourceObjectHandle={}, template={}", sourceObjectHandle, template); try { long hObject = pkcs11.C_CopyObject(sessionHandle, sourceObjectHandle, toOutCKAttributes(template), useUtf8); debugOut(method, "hObject={}", hObject); traceObject("copied object", hObject); return hObject; } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * Gets all present attributes of the given template object and writes them to the object to update * on the token (or in the session). Both parameters may refer to the same Java object. This is * possible, because this method only needs the object handle of the objectToUpdate, and gets the * attributes to set from the template. This means, an application can get the object using * createObject of findObject, then modify attributes of this Java object and then call this * method passing this object as both parameters. This will update the object on the token to the * values as modified in the Java object. * * @param objectToUpdateHandle The attributes of this object get updated. * @param template Gets all present attributes of this template object and sets this * attributes at the objectToUpdate. * @throws PKCS11Exception If updating the attributes fails. All or no attributes are updated. */ public void setAttributeValues(long objectToUpdateHandle, AttributeVector template) throws PKCS11Exception { final String method = "C_SetAttributeValue"; debugIn(method, "objectToUpdateHandle={}, template={}", objectToUpdateHandle, template); try { pkcs11.C_SetAttributeValue(sessionHandle, objectToUpdateHandle, toOutCKAttributes(template), useUtf8); debugOut(method); traceObject("object (after settingAttributeValues)", objectToUpdateHandle); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * Destroy a certain object on the token (or in the session). Give the object that you want to * destroy. This method uses only the internal object handle of the given object to identify the * object. * * @param objectHandle The object handle that should be destroyed. * @throws PKCS11Exception If the object could not be destroyed. */ public void destroyObject(long objectHandle) throws PKCS11Exception { final String method = "C_DestroyObject"; debugIn(method, "objectHandle={}", objectHandle); try { pkcs11.C_DestroyObject(sessionHandle, objectHandle); debugOut(method); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * Get the size of the specified object in bytes. This size specifies how much memory the object * takes up on the token. * * @param objectHandle The object to get the size for. * @return The object's size bytes. * @throws PKCS11Exception If determining the size fails. */ public long getObjectSize(long objectHandle) throws PKCS11Exception { try { return pkcs11.C_GetObjectSize(sessionHandle, objectHandle); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { throw module.convertException(e); } } /** * Initializes a find operations that provides means to find objects by passing a template object. * This method get all set attributes of the template object and searches for all objects on the * token that match with these attributes. * * @param template The object that serves as a template for searching. If this object is null, the find * operation will find all objects that this session can see. Notice, that only a user * session will see private objects. * @throws PKCS11Exception If initializing the find operation fails. */ public void findObjectsInit(AttributeVector template) throws PKCS11Exception { final String method = "C_FindObjectsInit"; debugIn(method, "template={}", template); try { pkcs11.C_FindObjectsInit(sessionHandle, toOutCKAttributes(template, true), useUtf8); debugOut(method); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * Finds objects that match the template object passed to findObjectsInit. The application must * call findObjectsInit before calling this method. With maxObjectCount the application can * specify how many objects to return at once; i.e. the application can get all found objects by * subsequent calls to this method like maxObjectCount(1) until it receives an empty array (this * method never returns null!). * * @param maxObjectCount Specifies how many objects to return with this call. * @return An array of found objects. The maximum size of this array is maxObjectCount, the * minimum length is 0. Never returns null. * @throws PKCS11Exception A plain PKCS11Exception if something during PKCS11 FindObject went wrong, a * PKCS11Exception with a nested PKCS11Exception if the Exception is raised during * object parsing. */ public long[] findObjects(int maxObjectCount) throws PKCS11Exception { final int countPerCall = 1000; if (maxObjectCount <= countPerCall) { return findObjects0(maxObjectCount); } else { List list = new LinkedList<>(); for (int i = 0; i < maxObjectCount; i+= countPerCall) { int numObjects = Math.min(countPerCall, maxObjectCount - i); long[] handles = findObjects0(numObjects); for (long handle : handles) { list.add(handle); } if (handles.length < numObjects) { break; } } long[] ret = new long[list.size()]; int idx = 0; for (Long handle : list) { ret[idx++] = handle; } return ret; } } private long[] findObjects0(int maxObjectCount) throws PKCS11Exception { final String method = "C_FindObjects"; debugIn(method, "maxObjectCount={}", maxObjectCount); try { long[] hObjects = pkcs11.C_FindObjects(sessionHandle, maxObjectCount); if (StaticLogger.isDebugEnabled()) { debugOut(method, "hObjects={}", Arrays.toString(hObjects)); } return hObjects; } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * Finalizes a find operation. The application must call this method to finalize a find operation * before attempting to start any other operation. * * @throws PKCS11Exception If finalizing the current find operation was not possible. */ public void findObjectsFinal() throws PKCS11Exception { final String method = "C_FindObjectsFinal"; debugIn(method); try { pkcs11.C_FindObjectsFinal(sessionHandle); debugOut(method); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } public long[] findAllObjectsSingle(AttributeVector template) throws PKCS11Exception { return findObjectsSingle(template, Integer.MAX_VALUE); } public long[] findObjectsSingle(AttributeVector template, int maxObjectCount) throws PKCS11Exception { findObjectsInit(template); try { return findObjects(maxObjectCount); } finally { findObjectsFinal(); } } /** * Initializes a new encryption operation. The application must call this method before calling * any other encrypt* operation. Before initializing a new operation, any currently pending * operation must be finalized using the appropriate *Final method (e.g. digestFinal()). There are * exceptions for dual-function operations. This method requires the mechanism to use for * encryption and the key for this operation. The key must have set its encryption flag. For the * mechanism the application may use a constant defined in the Mechanism class. Notice that the * key and the mechanism must be compatible; i.e. you cannot use a DES key with the RSA mechanism. * * @param mechanism The mechanism to use; e.g. Mechanism.DES_CBC. * @param keyHandle The decryption key to use. * @throws PKCS11Exception If initializing this operation failed. */ public void encryptInit(Mechanism mechanism, long keyHandle) throws PKCS11Exception { final String method = "C_EncryptInit"; mechanism.setModule(module); debugIn(method, "keyHandle={}, mechanism={}", keyHandle, mechanism); try { pkcs11.C_EncryptInit(sessionHandle, mechanism.toCkMechanism(), keyHandle, useUtf8); debugOut(method); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * Encrypts the given data with the key and mechanism given to the encryptInit method. This method * finalizes the current encryption operation; i.e. the application need (and should) not call * encryptFinal() after this call. For encrypting multiple pieces of data use encryptUpdate and * encryptFinal. * * @param plaintext the to-be-encrypted data * @return the encrypted data. Never returns {@code null}. * @throws PKCS11Exception If encrypting failed. */ public byte[] encrypt(byte[] plaintext) throws PKCS11Exception { final String method = "C_Encrypt"; debugIn(method, "plaintext.length={}", len(plaintext)); try { return toNonNull(method, pkcs11.C_Encrypt(sessionHandle, plaintext)); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } public byte[] encryptSingle(Mechanism mechanism, long keyHandle, byte[] plaintext) throws PKCS11Exception { encryptInit(mechanism, keyHandle); return encrypt(plaintext); } /** * This method can be used to encrypt multiple pieces of data; e.g. buffer-size pieces when * reading the data from a stream. Encrypts the given data with the key and mechanism given to the * encryptInit method. The application must call encryptFinal to get the final result of the * encryption after feeding in all data using this method. * * @param plaintextPat Piece of the to-be-encrypted data * @return the encrypted data for this update. Never returns {@code null}. * @throws PKCS11Exception If encrypting the data failed. */ public byte[] encryptUpdate(byte[] plaintextPat) throws PKCS11Exception { final String method = "C_EncryptUpdate"; debugIn(method, "plaintextPat.length={}", len(plaintextPat)); try { return toNonNull(method, pkcs11.C_EncryptUpdate(sessionHandle, plaintextPat)); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * This method finalizes an encryption operation and returns the final result. Use this method, if * you fed in the data using encryptUpdate. If you used the encrypt(byte[]) method, you need not * (and shall not) call this method, because encrypt(byte[]) finalizes the encryption itself. * * @return the last part of the encrypted data. Never returns {@code null}. * @throws PKCS11Exception If calculating the final result failed. */ public byte[] encryptFinal() throws PKCS11Exception { final String method = "C_EncryptFinal"; debugIn(method); try { return toNonNull(method, pkcs11.C_EncryptFinal(sessionHandle)); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * Initializes a new message encryption operation. The application must call this method before calling * any other encryptMessage* operation. Before initializing a new operation, any currently pending * operation must be finalized using the appropriate *Final method (e.g. digestFinal()). There are * exceptions for dual-function operations. This method requires the mechanism to use for * encryption and the key for this operation. The key must have set its encryption flag. For the * mechanism the application may use a constant defined in the Mechanism class. Notice that the * key and the mechanism must be compatible; i.e. you cannot use a DES key with the RSA mechanism. * * @param mechanism The mechanism to use; e.g. Mechanism.DES_CBC. * @param keyHandle The decryption key to use. * @throws PKCS11Exception If initializing this operation failed. */ public void messageEncryptInit(Mechanism mechanism, long keyHandle) throws PKCS11Exception { final String method = "C_MessageEncryptInit"; mechanism.setModule(module); debugIn(method, "keyHandle={}, mechanism={}", keyHandle, mechanism); try { pkcs11.C_MessageEncryptInit(sessionHandle, mechanism.toCkMechanism(), keyHandle, useUtf8); debugOut(method); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * Encrypts the given message with the key and mechanism given to the MessageEncryptInit method. * Contrary to the encrypt-Function, the encryptMessage-Function can be called any number of times and does * not finalize the encryption-operation * * @param params The parameter object * @param associatedData The associated Data for AEAD Mechanisms * @param plaintext The plaintext getting encrypted * @return The ciphertext. Never returns {@code null}. * @throws PKCS11Exception If encrypting failed. */ public byte[] encryptMessage(CkParams params, byte[] associatedData, byte[] plaintext) throws PKCS11Exception { final String method = "C_EncryptMessage"; setModule(params); Object paramObject = toCkParameters(params); debugIn(method, "associatedData.length={}, plaintext.length={}", len(associatedData), len(plaintext)); try { byte[] rv = pkcs11.C_EncryptMessage(sessionHandle, paramObject, associatedData, plaintext, useUtf8); if (params instanceof CkMessageParams) { ((CkMessageParams) params).setValuesFromPKCS11Object(paramObject); } return toNonNull(method, rv); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * Starts a multipart message-encryption operation. Can only be called when an encryption operation has been * initialized before. * * @param params The IV or nonce * @param associatedData The associated Data for AEAD Mechanisms * @throws PKCS11Exception in case of error. */ public void encryptMessageBegin(CkParams params, byte[] associatedData) throws PKCS11Exception { final String method = "C_EncryptMessageBegin"; setModule(params); debugIn(method, "associatedData.length={}, params={}", len(associatedData), params); try { pkcs11.C_EncryptMessageBegin(sessionHandle, toCkParameters(params), associatedData, useUtf8); debugOut(method); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * Encrypts one part of a multipart encryption operation. The multipart operation must have been started * with encryptMessageBegin before calling this function. If the isLastOperation is set, the multipart operation * finishes and if present the TAG or MAC is returned in the parameters. * * @param params The parameter object * @param plaintext The associated Data for AEAD Mechanisms * @param isLastOperation If this is the last part of the multipart message encryption, this should be true * @return The encrypted message part. Never returns {@code null}. * @throws PKCS11Exception in case of error. */ public byte[] encryptMessageNext(CkParams params, byte[] plaintext, boolean isLastOperation) throws PKCS11Exception { setModule(params); Object paramObject = toCkParameters(params); if (params instanceof CkMessageParams) { ((CkMessageParams) params).setValuesFromPKCS11Object(paramObject); } final String method = "C_EncryptMessageNext"; debugIn(method, "plaintext.length={}, isLastOperation={}, params={}", len(plaintext), isLastOperation, params); try { return toNonNull(method, pkcs11.C_EncryptMessageNext(sessionHandle, paramObject, plaintext, isLastOperation ? CKF_END_OF_MESSAGE : 0, useUtf8)); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * Finishes a Message Encryption Operation which has previously been started with messageEncryptInit. * * @throws PKCS11Exception in case of error. */ public void messageEncryptFinal() throws PKCS11Exception { final String method = "C_MessageEncryptFinal"; debugIn(method); try { pkcs11.C_MessageEncryptFinal(sessionHandle); debugOut(method); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * Initializes a new decryption operation. The application must call this method before calling * any other decrypt* operation. Before initializing a new operation, any currently pending * operation must be finalized using the appropriate *Final method (e.g. digestFinal()). There are * exceptions for dual-function operations. This method requires the mechanism to use for * decryption and the key for this operation. The key must have set its decryption flag. For the * mechanism the application may use a constant defined in the Mechanism class. Notice that the * key and the mechanism must be compatible; i.e. you cannot use a DES key with the RSA mechanism. * * @param mechanism The mechanism to use; e.g. Mechanism.DES_CBC. * @param keyHandle The decryption key to use. * @throws PKCS11Exception If initializing this operation failed. */ public void decryptInit(Mechanism mechanism, long keyHandle) throws PKCS11Exception { final String method = "C_DecryptInit"; mechanism.setModule(module); debugIn(method, "keyHandle={}, mechanism={}", keyHandle, mechanism); try { pkcs11.C_DecryptInit(sessionHandle, mechanism.toCkMechanism(), keyHandle, useUtf8); debugOut(method); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * Decrypts the given data with the key and mechanism given to the decryptInit method. This method * finalizes the current decryption operation; i.e. the application need (and should) not call * decryptFinal() after this call. For decrypting multiple pieces of data use decryptUpdate and * decryptFinal. * * @param ciphertext the to-be-decrypted data * @return the decrypted data. Never returns {@code null}. * @throws PKCS11Exception If decrypting failed. */ public byte[] decrypt(byte[] ciphertext) throws PKCS11Exception { final String method = "C_Decrypt"; debugIn(method, "ciphertext.length={}", len(ciphertext)); try { return toNonNull(method, pkcs11.C_Decrypt(sessionHandle, ciphertext)); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } public byte[] decryptSingle(Mechanism mechanism, long keyHandle, byte[] ciphertext) throws PKCS11Exception { decryptInit(mechanism, keyHandle); return decrypt(ciphertext); } /** * This method can be used to decrypt multiple pieces of data; e.g. buffer-size pieces when * reading the data from a stream. Decrypts the given data with the key and mechanism given to the * decryptInit method. The application must call decryptFinal to get the final result of the * encryption after feeding in all data using this method. * * @param ciphertextPart Piece of the to-be-decrypted data for this update * @return the decrypted data for this update. Never returns {@code null}. * @throws PKCS11Exception If decrypting the data failed. */ public byte[] decryptUpdate(byte[] ciphertextPart) throws PKCS11Exception { final String method = "C_DecryptUpdate"; debugIn(method, "ciphertextPart.length={}", len(ciphertextPart)); try { return toNonNull(method, pkcs11.C_DecryptUpdate(sessionHandle, ciphertextPart)); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * This method finalizes a decryption operation and returns the final result. Use this method, if * you fed in the data using decryptUpdate. If you used the decrypt(byte[]) method, you need not * (and shall not) call this method, because decrypt(byte[]) finalizes the decryption itself. * * @return the last part of decrypted data. Never returns {@code null}. * @throws PKCS11Exception If calculating the final result failed. */ public byte[] decryptFinal() throws PKCS11Exception { final String method = "C_DecryptFinal"; debugIn(method); try { return toNonNull(method, pkcs11.C_DecryptFinal(sessionHandle)); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * Initializes a new message decryption operation. The application must call this method before calling * any other decryptMessage* operation. Before initializing a new operation, any currently pending * operation must be finalized using the appropriate *Final method (e.g. digestFinal()). There are * exceptions for dual-function operations. This method requires the mechanism to use for * encryption and the key for this operation. The key must have set its encryption flag. For the * mechanism the application may use a constant defined in the Mechanism class. Notice that the * key and the mechanism must be compatible; i.e. you cannot use a DES key with the RSA mechanism. * * @param mechanism The mechanism to use; e.g. Mechanism.DES_CBC. * @param keyHandle The decryption key to use. * @throws PKCS11Exception If initializing this operation failed. */ public void messageDecryptInit(Mechanism mechanism, long keyHandle) throws PKCS11Exception { final String method = "C_MessageDecryptInit"; mechanism.setModule(module); debugIn(method, "keyHandle={}, mechanism={}", keyHandle, mechanism); try { pkcs11.C_MessageDecryptInit(sessionHandle, mechanism.toCkMechanism(), keyHandle, useUtf8); debugOut(method); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * Decrypts the given message with the key and mechanism given to the MessageDecryptInit method. * Contrary to the decrypt-Function, the decryptMessage-Function can be called any number of times and does * not finalize the decryption-operation * * @param params The parameter object * @param associatedData The associated Data for AEAD Mechanisms * @param ciphertext The to-be-decrypted data * @return The ciphertext. Never returns {@code null}. * @throws PKCS11Exception If encrypting failed. */ public byte[] decryptMessage(CkParams params, byte[] associatedData, byte[] ciphertext) throws PKCS11Exception { final String method = "C_DecryptMessage"; setModule(params); debugIn(method, "associatedData.length={}, ciphertext.length={}, params={}", len(associatedData), len(ciphertext), params); try { return toNonNull(method, pkcs11.C_DecryptMessage(sessionHandle, toCkParameters(params), associatedData, ciphertext, useUtf8)); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * Starts a multipart message-decryption operation. * * @param params The parameter object * @param associatedData The associated Data for AEAD Mechanisms * @throws PKCS11Exception in case of error. */ public void decryptMessageBegin(CkParams params, byte[] associatedData) throws PKCS11Exception { final String method = "C_DecryptMessageBegin"; setModule(params); debugIn(method, "associatedData.length={}, params={}", len(associatedData), params); try { pkcs11.C_DecryptMessageBegin(sessionHandle, toCkParameters(params), associatedData, useUtf8); debugOut(method); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * Decrypts one part of a multipart decryption operation. The multipart operation must have been started * with decryptMessageBegin before calling this function. If the isLastOperation is set, the multipart operation * finishes. * * @param params The parameter object * @param ciphertext The ciphertext getting decrypted * @param isLastOperation If this is the last part of the multipart message encryption, this should be true * @return the decrypted message part. Never returns {@code null}. * @throws PKCS11Exception in case of error. */ public byte[] decryptMessageNext(CkParams params, byte[] ciphertext, boolean isLastOperation) throws PKCS11Exception { final String method = "C_DecryptMessageNext"; setModule(params); debugIn(method, "ciphertext.length={}, isLastOperation={}, params={}", len(ciphertext), isLastOperation, params); try { return toNonNull(method, pkcs11.C_DecryptMessageNext(sessionHandle, toCkParameters(params), ciphertext, isLastOperation ? CKF_END_OF_MESSAGE : 0, useUtf8)); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * finishes multipart message decryption operation. * * @throws PKCS11Exception in case of error. */ public void messageDecryptFinal() throws PKCS11Exception { final String method = "C_MessageDecryptFinal"; debugIn(method); try { pkcs11.C_MessageDecryptFinal(sessionHandle); debugOut(method); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * Initializes a new digesting operation. The application must call this method before calling any * other digest* operation. Before initializing a new operation, any currently pending operation * must be finalized using the appropriate *Final method (e.g. digestFinal()). There are * exceptions for dual-function operations. This method requires the mechanism to use for * digesting for this operation. For the mechanism the application may use a constant defined in * the Mechanism class. * * @param mechanism The mechanism to use; e.g. Mechanism.SHA_1. * @throws PKCS11Exception If initializing this operation failed. */ public void digestInit(Mechanism mechanism) throws PKCS11Exception { final String method = "C_DigestInit"; mechanism.setModule(module); debugIn(method, "mechanism={}", mechanism); try { pkcs11.C_DigestInit(sessionHandle, mechanism.toCkMechanism(), useUtf8); debugOut(method); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * Digests the given data with the mechanism given to the digestInit method. This method finalizes * the current digesting operation; i.e. the application need (and should) not call digestFinal() * after this call. For digesting multiple pieces of data use digestUpdate and digestFinal. * * @param data the to-be-digested data * @return the message digest. Never returns {@code null}. * @throws PKCS11Exception If digesting the data failed. */ public byte[] digest(byte[] data) throws PKCS11Exception { final String method = "C_Digest"; debugIn(method, "data.length={}", len(data)); try { return toNonNull(method, pkcs11.C_Digest(sessionHandle, data)); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } public byte[] digestSingle(Mechanism mechanism, byte[] data) throws PKCS11Exception { digestInit(mechanism); return digest(data); } /** * This method can be used to digest multiple pieces of data; e.g. buffer-size pieces when reading * the data from a stream. Digests the given data with the mechanism given to the digestInit * method. The application must call digestFinal to get the final result of the digesting after * feeding in all data using this method. * * @param dataPart Piece of the to-be-digested data * @throws PKCS11Exception If digesting the data failed. */ public void digestUpdate(byte[] dataPart) throws PKCS11Exception { final String method = "C_DigestUpdate"; debugIn(method, "dataPart.length={}", len(dataPart)); try { pkcs11.C_DigestUpdate(sessionHandle, dataPart); debugOut(method); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * This method is similar to digestUpdate and can be combined with it during one digesting * operation. This method digests the value of the given secret key. * * @param keyHandle The key to digest the value of. * @throws PKCS11Exception If digesting the key failed. */ public void digestKey(long keyHandle) throws PKCS11Exception { final String method = "C_DigestKey"; debugIn(method, "keyHandle={}", keyHandle); try { pkcs11.C_DigestKey(sessionHandle, keyHandle); debugOut(method); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * This method finalizes a digesting operation and returns the final result. Use this method, if * you fed in the data using digestUpdate and/or digestKey. If you used the digest(byte[]) method, * you need not (and shall not) call this method, because digest(byte[]) finalizes the digesting * itself. * * @return the message digest. Never returns {@code null}. * @throws PKCS11Exception If calculating the final message digest failed. */ public byte[] digestFinal() throws PKCS11Exception { final String method = "C_DigestFinal"; debugIn(method); try { return toNonNull(method, pkcs11.C_DigestFinal(sessionHandle)); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * This method finalizes a digesting operation and returns the final result. Use this method, if * you fed in the data using digestUpdate and/or digestKey. If you used the digest(byte[]) method, * you need not (and shall not) call this method, because digest(byte[]) finalizes the digesting * itself. * * @param out buffer for the message digest * @param outOfs buffer offset for the message digest * @param outLen buffer size for the message digest * @return the length of message digest * @throws PKCS11Exception If calculating the final message digest failed. */ public int digestFinal(byte[] out, int outOfs, int outLen) throws PKCS11Exception { byte[] digest = digestFinal(); if (digest.length > outLen) { throw new PKCS11Exception(CKR_BUFFER_TOO_SMALL, "CKR_BUFFER_TOO_SMALL"); } System.arraycopy(digest, 0, out, outOfs, digest.length); return digest.length; } /** * Initializes a new signing operation. Use it for signatures and MACs. The application must call * this method before calling any other sign* operation. Before initializing a new operation, any * currently pending operation must be finalized using the appropriate *Final method (e.g. * digestFinal()). There are exceptions for dual-function operations. This method requires the * mechanism to use for signing and the key for this operation. The key must have set its sign * flag. For the mechanism the application may use a constant defined in the Mechanism class. * Notice that the key and the mechanism must be compatible; i.e. you cannot use a DES key with * the RSA mechanism. * * @param mechanism The mechanism to use; e.g. Mechanism.RSA_PKCS. * @param keyHandle The signing key to use. * @throws PKCS11Exception If initializing this operation failed. */ public void signInit(Mechanism mechanism, long keyHandle) throws PKCS11Exception { final String method = "C_SignInit"; mechanism.setModule(module); debugIn(method, "keyHandle={}, mechanism={}", keyHandle, mechanism); initSignVerify(mechanism, keyHandle); try { pkcs11.C_SignInit(sessionHandle, mechanism.toCkMechanism(), keyHandle, useUtf8); debugOut(method); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } private void initSignVerify(Mechanism mechanism, long keyHandle) { this.signOrVerifyKeyHandle = keyHandle; long code = mechanism.getMechanismCode(); if (code == CKM_ECDSA || code == CKM_ECDSA_SHA1 || code == CKM_ECDSA_SHA224 || code == CKM_ECDSA_SHA256 || code == CKM_ECDSA_SHA384 || code == CKM_ECDSA_SHA512 || code == CKM_ECDSA_SHA3_224 || code == CKM_ECDSA_SHA3_256 || code == CKM_ECDSA_SHA3_384 || code == CKM_ECDSA_SHA3_512) { signatureType = SIGN_TYPE_ECDSA; } else if (code == CKM_VENDOR_SM2 || code == CKM_VENDOR_SM2_SM3) { signatureType = SIGN_TYPE_SM2; } else { signatureType = 0; } if (mechanism.getParameters() instanceof CkParamsWithExtra) { signVerifyExtraParams = ((CkParamsWithExtra) mechanism.getParameters()).getExtraParams(); } else { signVerifyExtraParams = null; } } /** * Signs the given data with the key and mechanism given to the signInit method. This method * finalizes the current signing operation; i.e. the application need (and should) not call * signFinal() after this call. For signing multiple pieces of data use signUpdate and signFinal. * * @param data The data to sign. * @return The signed data. Never returns {@code null}. * @throws PKCS11Exception If signing the data failed. */ public byte[] sign(byte[] data) throws PKCS11Exception { final String method = "C_Sign"; debugIn(method, "data.length={}", len(data)); try { byte[] sigValue = pkcs11.C_Sign(sessionHandle, data); debugOut(method, "rv.length={}", len(sigValue)); return toNonNull(fixSignOutput(sigValue)); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } public byte[] signSingle(Mechanism mechanism, long keyHandle, byte[] data) throws PKCS11Exception { signInit(mechanism, keyHandle); return sign(data); } /** * This method can be used to sign multiple pieces of data; e.g. buffer-size pieces when reading * the data from a stream. Signs the given data with the mechanism given to the signInit method. * The application must call signFinal to get the final result of the signing after feeding in all * data using this method. * * @param dataPart Piece of the to-be-signed data * @throws PKCS11Exception If signing the data failed. */ public void signUpdate(byte[] dataPart) throws PKCS11Exception { final String method = "C_SignUpdate"; debugIn(method, "dataPart.length={}", len(dataPart)); try { pkcs11.C_SignUpdate(sessionHandle, dataPart); debugOut(method); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * This method can be used to sign multiple pieces of data; e.g. buffer-size pieces when reading * the data from a stream. Signs the given data with the mechanism given to the signInit method. * The application must call signFinal to get the final result of the signing after feeding in all * data using this method. * * @param in buffer containing the to-be-signed data * @param inOfs buffer offset of the to-be-signed data * @param inLen length of the to-be-signed data * @throws PKCS11Exception If signing the data failed. */ public void signUpdate(byte[] in, int inOfs, int inLen) throws PKCS11Exception { final String method = "C_SignUpdate"; debugIn(method, "in.length={}", len(in)); try { if (inOfs == 0 && inLen == in.length) { pkcs11.C_SignUpdate(sessionHandle, in); } else { pkcs11.C_SignUpdate(sessionHandle, Arrays.copyOfRange(in, inOfs, inOfs + inLen)); } debugOut(method); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * This method finalizes a signing operation and returns the final result. Use this method, if you * fed in the data using signUpdate. If you used the sign(byte[]) method, you need not (and shall * not) call this method, because sign(byte[]) finalizes the signing operation itself. * * @return The final result of the signing operation; i.e. the signature * value. Never returns {@code null}. * @throws PKCS11Exception If calculating the final signature value failed. */ public byte[] signFinal() throws PKCS11Exception { final String method = "C_SignFinal"; debugIn(method); try { byte[] sigValue = pkcs11.C_SignFinal(sessionHandle); debugOut(method, "rv.length={}", len(sigValue)); return toNonNull(fixSignOutput(sigValue)); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } private byte[] fixSignOutput(byte[] signatureValue) { if (signatureType == 0) { return signatureValue; } synchronized (module) { if (signatureType == SIGN_TYPE_ECDSA) { Boolean b = module.getEcdsaSignatureFixNeeded(); if (b == null) { StaticLogger.info("EcdsaSignatureFixNeeded: null"); } else { StaticLogger.debug("EcdsaSignatureFixNeeded: {}", b); } if (b == null || b) { byte[] fixedSigValue; if (signVerifyExtraParams != null) { int rOrSLen = (signVerifyExtraParams.ecOrderBitSize() + 7) / 8; fixedSigValue = Functions.fixECDSASignature(signatureValue, rOrSLen); } else { // get the ecParams byte[] ecParams; try { ecParams = getAttrValues(signOrVerifyKeyHandle, CKA_EC_PARAMS).ecParams(); } catch (PKCS11Exception e) { StaticLogger.debug("error getting CKA_EC_PARAMS for key {}", signOrVerifyKeyHandle); return signatureValue; } if (ecParams == null) { StaticLogger.debug("found no CKA_EC_PARAMS for key {}", signOrVerifyKeyHandle); return signatureValue; } fixedSigValue = Functions.fixECDSASignature(signatureValue, ecParams); } boolean fixed = !Arrays.equals(fixedSigValue, signatureValue); if (b == null) { StaticLogger.info("Set EcdsaSignatureFixNeeded to {}", fixed); module.setEcdsaSignatureFixNeeded(fixed); } return fixedSigValue; } } else if (signatureType == SIGN_TYPE_SM2) { Boolean b = module.getSm2SignatureFixNeeded(); if (b == null) { StaticLogger.info("Sm2SignatureFixNeeded: null"); } else { StaticLogger.debug("Sm2SignatureFixNeeded: {}", b); } if (b == null || b) { byte[] fixedSigValue = Functions.fixECDSASignature(signatureValue, 32); boolean fixed = !Arrays.equals(fixedSigValue, signatureValue); if (b == null) { StaticLogger.info("Set Sm2SignatureFixNeeded to {}", fixed); module.setSm2SignatureFixNeeded(fixed); } return fixedSigValue; } } return signatureValue; } } private byte[] fixSignatureToVerify(byte[] signatureValue) { if (signatureType == SIGN_TYPE_ECDSA) { if (module.hasVendorBehaviour(PKCS11Module.BEHAVIOUR_ECDSA_SIGNATURE_X962)) { return Functions.dsaSigPlainToX962(signatureValue); } } else if (signatureType == SIGN_TYPE_SM2) { if (module.hasVendorBehaviour(PKCS11Module.BEHAVIOUR_SM2_SIGNATURE_X962)) { return Functions.dsaSigPlainToX962(signatureValue); } } return signatureValue; } /** * Initializes a new signing operation for signing with recovery. The application must call this * method before calling signRecover. Before initializing a new operation, any currently pending * operation must be finalized using the appropriate *Final method (e.g. digestFinal()). There are * exceptions for dual-function operations. This method requires the mechanism to use for signing * and the key for this operation. The key must have set its sign-recover flag. For the mechanism * the application may use a constant defined in the Mechanism class. Notice that the key and the * mechanism must be compatible; i.e. you cannot use a DES key with the RSA mechanism. * * @param mechanism The mechanism to use; e.g. Mechanism.RSA_9796. * @param keyHandle The signing key to use. * @throws PKCS11Exception If initializing this operation failed. */ public void signRecoverInit(Mechanism mechanism, long keyHandle) throws PKCS11Exception { final String method = "C_SignRecoverInit"; mechanism.setModule(module); debugIn(method, "keyHandle={}, mechanism={}", keyHandle, mechanism); try { pkcs11.C_SignRecoverInit(sessionHandle, mechanism.toCkMechanism(), keyHandle, useUtf8); debugOut(method); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * Signs the given data with the key and mechanism given to the signRecoverInit method. This * method finalizes the current sign-recover operation; there is no equivalent method to * signUpdate for signing with recovery. * * @param data the to-be-signed data * @return the signed data. Never returns {@code null}. * @throws PKCS11Exception If signing the data failed. */ public byte[] signRecover(byte[] data) throws PKCS11Exception { final String method = "C_SignRecover"; debugIn(method, "data.length={}", len(data)); try { return toNonNull(method, pkcs11.C_SignRecover(sessionHandle, data)); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } public byte[] signRecoverSingle(Mechanism mechanism, long keyHandle, byte[] data) throws PKCS11Exception { signRecoverInit(mechanism, keyHandle); return signRecover(data); } /** * @param mechanism the mechanism parameter to use * @param keyHandle the key to sign the data with * @throws PKCS11Exception in case of error. */ public void messageSignInit(Mechanism mechanism, long keyHandle) throws PKCS11Exception { final String method = "C_MessageSignInit"; mechanism.setModule(module); initSignVerify(mechanism, keyHandle); debugIn(method, "keyHandle={}, mechanism={}", keyHandle, mechanism); try { pkcs11.C_MessageSignInit(sessionHandle, mechanism.toCkMechanism(), keyHandle, useUtf8); debugOut(method); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * @param params the mechanism parameter to use * @param data the data to sign * @return the signature. Never returns {@code null}. * @throws PKCS11Exception if signing failed. */ public byte[] signMessage(CkParams params, byte[] data) throws PKCS11Exception { final String method = "C_SignMessage"; setModule(params); debugIn(method, "data.length={}, params={}", len(data), params); try { return toNonNull(method, pkcs11.C_SignMessage(sessionHandle, toCkParameters(params), data, useUtf8)); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * SignMessageBegin begins a multiple-part message signature operation, where the signature is an * appendix to the message. * * @param params the mechanism parameter to use * @throws PKCS11Exception in case of error. */ public void signMessageBegin(CkParams params) throws PKCS11Exception { final String method = "C_SignMessageBegin"; setModule(params); debugIn(method, "params={}", params); try { pkcs11.C_SignMessageBegin(sessionHandle, toCkParameters(params), useUtf8); debugOut(method); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * SignMessageNext continues a multiple-part message signature operation, processing another data * part, or finishes a multiple-part message signature operation, returning the signature. * * @param params the mechanism parameter to use * @param data the message to sign * @param isLastOperation specifies if this is the last part of this message. * @return the signature. Never returns {@code null}. * @throws PKCS11Exception in case of error. */ public byte[] signMessageNext(CkParams params, byte[] data, boolean isLastOperation) throws PKCS11Exception { final String method = "C_SignMessageNext"; setModule(params); debugIn(method, "data.length={}, isLastOperation={}, params={}", len(data), isLastOperation, params); try { byte[] signature = pkcs11.C_SignMessageNext(sessionHandle, toCkParameters(params), data, isLastOperation, useUtf8); return toNonNull(method, fixSignOutput(signature)); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * finishes a message-based signing process. * The message-based signing process MUST have been initialized with messageSignInit. * * @throws PKCS11Exception in case of error. */ public void messageSignFinal() throws PKCS11Exception { final String method = "C_MessageSignFinal"; debugIn(method); try { pkcs11.C_MessageSignFinal(sessionHandle); debugOut(method); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * Initializes a new verification operation. You can use it for verifying signatures and MACs. The * application must call this method before calling any other verify* operation. Before * initializing a new operation, any currently pending operation must be finalized using the * appropriate *Final method (e.g. digestFinal()). There are exceptions for dual-function * operations. This method requires the mechanism to use for verification and the key for this * operation. The key must have set its verify flag. For the mechanism the application may use a * constant defined in the Mechanism class. Notice that the key and the mechanism must be * compatible; i.e. you cannot use a DES key with the RSA mechanism. * * @param mechanism The mechanism to use; e.g. Mechanism.RSA_PKCS. * @param keyHandle The verification key to use. * @throws PKCS11Exception If initializing this operation failed. */ public void verifyInit(Mechanism mechanism, long keyHandle) throws PKCS11Exception { final String method = "C_VerifyInit"; mechanism.setModule(module); initSignVerify(mechanism, keyHandle); debugIn(method, "keyHandle={}, mechanism={}", keyHandle, mechanism); try { pkcs11.C_VerifyInit(sessionHandle, mechanism.toCkMechanism(), keyHandle, useUtf8); debugOut(method); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * Verifies the given signature against the given data with the key and mechanism given to the * verifyInit method. This method finalizes the current verification operation; i.e. the * application need (and should) not call verifyFinal() after this call. For verifying with * multiple pieces of data use verifyUpdate and verifyFinal. This method throws an exception, if * the verification of the signature fails. * * @param data The data that was signed. * @param signature The signature or MAC to verify. * @throws PKCS11Exception If verifying the signature fails. This is also the case, if the signature is * forged. */ public void verify(byte[] data, byte[] signature) throws PKCS11Exception { final String method = "C_Verify"; byte[] realSig = fixSignatureToVerify(signature); debugIn(method, "data.length={}, signature.length={}", len(data), len(realSig)); try { pkcs11.C_Verify(sessionHandle, data, realSig); debugOut(method); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } public void verifySingle(Mechanism mechanism, long keyHandle, byte[] data, byte[] signature) throws PKCS11Exception { verifyInit(mechanism, keyHandle); verify(data, signature); } /** * This method can be used to verify a signature with multiple pieces of data; e.g. buffer-size * pieces when reading the data from a stream. To verify the signature or MAC call verifyFinal * after feeding in all data using this method. * * @param dataPart Piece of the to-be-verified data. * @throws PKCS11Exception If verifying (e.g. digesting) the data failed. */ public void verifyUpdate(byte[] dataPart) throws PKCS11Exception { final String method = "C_VerifyUpdate"; debugIn(method, "dataPart.length={}", len(dataPart)); try { pkcs11.C_VerifyUpdate(sessionHandle, dataPart); debugOut(method); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * This method finalizes a verification operation. Use this method, if you fed in the data using * verifyUpdate. If you used the verify(byte[]) method, you need not (and shall not) call this * method, because verify(byte[]) finalizes the verification operation itself. If this method * verified the signature successfully, it returns normally. If the verification of the signature * fails, e.g. if the signature was forged or the data was modified, this method throws an * exception. * * @param signature The signature value. * @throws PKCS11Exception If verifying the signature fails. This is also the case, if the signature is * forged. */ public void verifyFinal(byte[] signature) throws PKCS11Exception { final String method = "C_VerifyFinal"; byte[] realSig = fixSignatureToVerify(signature); debugIn(method, "signature.length={}", len(realSig)); try { pkcs11.C_VerifyFinal(sessionHandle, realSig); debugOut(method); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * Initializes a new verification operation for verification with data recovery. The application * must call this method before calling verifyRecover. Before initializing a new operation, any * currently pending operation must be finalized using the appropriate *Final method (e.g. * digestFinal()). This method requires the mechanism to use for verification and the key for this * operation. The key must have set its verify-recover flag. For the mechanism the application may * use a constant defined in the Mechanism class. Notice that the key and the mechanism must be * compatible; i.e. you cannot use a DES key with the RSA mechanism. * * @param mechanism The mechanism to use; e.g. Mechanism.RSA_9796. * @param keyHandle The verification key to use. * @throws PKCS11Exception If initializing this operation failed. */ public void verifyRecoverInit(Mechanism mechanism, long keyHandle) throws PKCS11Exception { final String method = "C_VerifyRecoverInit"; mechanism.setModule(module); debugIn(method, "keyHandle={}, mechanism={}", keyHandle, mechanism); try { pkcs11.C_VerifyRecoverInit(sessionHandle, mechanism.toCkMechanism(), keyHandle, useUtf8); debugOut(method); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * Verifies the given data with the key and mechanism given to the verifyRecoverInit method. This * method finalizes the current verify-recover operation; there is no equivalent method to * verifyUpdate for signing with recovery. * * @param data the to-be-verified data * @return the verified data. Never returns {@code null}. * @exception PKCS11Exception * If signing the data failed. */ public byte[] verifyRecover(byte[] data) throws PKCS11Exception { final String method = "C_VerifyRecover"; debugIn(method, "data.length={}", len(data)); try { return toNonNull(method, pkcs11.C_VerifyRecover(sessionHandle, data)); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } public byte[] verifyRecoverSingle(Mechanism mechanism, long keyHandle, byte[] data) throws PKCS11Exception { verifyRecoverInit(mechanism, keyHandle); return verifyRecover(data); } /** * Initiates a message verification operation, preparing a session for one or * more verification operations (where the signature is an appendix to the data) that use the same * verification mechanism and verification key. * * @param mechanism * the mechanism to use * @param keyHandle * the verification key to use * @throws PKCS11Exception in case of error. */ public void messageVerifyInit(Mechanism mechanism, long keyHandle) throws PKCS11Exception { final String method = "C_MessageVerifyInit"; mechanism.setModule(module); initSignVerify(mechanism, keyHandle); debugIn(method, "keyHandle={}, mechanism={}", keyHandle, mechanism); try { pkcs11.C_MessageVerifyInit(sessionHandle, mechanism.toCkMechanism(), keyHandle, useUtf8); debugOut(method); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * Verifies a signature on a message in a single part operation. messageVerifyInit must previously * been called on the session. * * @param params * the mechanism parameter to use * @param data * the message to verify with the signature * @param signature * the signature of the message * @throws PKCS11Exception if the message cant be verified */ public void verifyMessage(CkParams params, byte[] data, byte[] signature) throws PKCS11Exception { final String method = "C_VerifyMessage"; setModule(params); debugIn(method, "data.length={}, signature.length={}, params={}", len(data), len(signature), params); try { pkcs11.C_VerifyMessage(sessionHandle, toCkParameters(params), data, fixSignatureToVerify(signature), useUtf8); debugOut(method); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * Begins a multipart message verification operation. * MessageVerifyInit must previously been called on the session * * @param params * the mechanism parameter to use * @throws PKCS11Exception in case of error. */ public void verifyMessageBegin(CkParams params) throws PKCS11Exception { final String method = "C_VerifyMessageBegin"; setModule(params); debugIn(method, "params={}", params); try { pkcs11.C_VerifyMessageBegin(sessionHandle, toCkParameters(params), useUtf8); debugOut(method); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * continues a multiple-part message verification operation, processing another data * part, or finishes a multiple-part message verification operation, checking the signature. * The signature argument is set to NULL if there is more data part to follow, or set to a non-NULL value * (pointing to the signature to verify) if this is the last data part. * * @param params * the mechanism parameter to use * @param data * the data to be verified * @param signature * NUll if there is data follow, the signature if it is the last part of the signing operation * @throws PKCS11Exception * if The Signature is invalid */ public void verifyMessageNext(CkParams params, byte[] data, byte[] signature) throws PKCS11Exception { final String method = "C_VerifyMessageNext"; setModule(params); debugIn(method, "data.length={}, signature.length={}, params={}", len(data), len(signature), params); try { pkcs11.C_VerifyMessageNext(sessionHandle, toCkParameters(params), data, fixSignatureToVerify(signature), useUtf8); debugOut(method); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * finishes a message-based verification process. * The message-based verification process must have been initialized with messageVerifyInit. * @throws PKCS11Exception in case of error. */ public void messageVerifyFinal() throws PKCS11Exception { final String method = "C_MessageVerifyFinal"; debugIn(method); try { pkcs11.C_MessageVerifyFinal(sessionHandle); debugOut(method); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * Dual-function. Continues a multipart dual digest and encryption operation. This method call can * also be combined with calls to digestUpdate, digestKey and encryptUpdate. Call digestFinal and * encryptFinal to get the final results. * * @param part * The piece of data to digest and encrypt. * @return The intermediate result of the encryption. Never returns {@code null}. * @exception PKCS11Exception * If digesting or encrypting the data failed. */ public byte[] digestEncryptedUpdate(byte[] part) throws PKCS11Exception { final String method = "C_DigestEncryptUpdate"; debugIn(method, "part.length={}", len(part)); try { return toNonNull(method, pkcs11.C_DigestEncryptUpdate(sessionHandle, part)); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * Dual-function. Continues a multipart dual decrypt and digest operation. This method call can * also be combined with calls to digestUpdate, digestKey and decryptUpdate. It is the recovered * plaintext that gets digested in this method call, not the given encryptedPart. Call digestFinal * and decryptFinal to get the final results. * * @param part * The piece of data to decrypt and digest. * @return The intermediate result of the decryption; the decrypted data. Never returns {@code null}. * @exception PKCS11Exception * If decrypting or digesting the data failed. */ public byte[] decryptDigestUpdate(byte[] part) throws PKCS11Exception { final String method = "C_DecryptDigestUpdate"; debugIn(method, "part.length={}", len(part)); try { return toNonNull(method, pkcs11.C_DecryptDigestUpdate(sessionHandle, part)); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * Dual-function. Continues a multipart dual sign and encrypt operation. Calls to this method can * also be combined with calls to signUpdate and encryptUpdate. Call signFinal and encryptFinal to * get the final results. * * @param part * The piece of data to sign and encrypt. * @return The intermediate result of the encryption; the encrypted data. Never returns {@code null}. * @exception PKCS11Exception * If signing or encrypting the data failed. */ public byte[] signEncryptUpdate(byte[] part) throws PKCS11Exception { final String method = "C_SignEncryptUpdate"; debugIn(method, "part.length={}", len(part)); try { return toNonNull(method, pkcs11.C_SignEncryptUpdate(sessionHandle, part)); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * Dual-function. Continues a multipart dual decrypt and verify operation. This method call can * also be combined with calls to decryptUpdate and verifyUpdate. It is the recovered plaintext * that gets verified in this method call, not the given encryptedPart. Call decryptFinal and * verifyFinal to get the final results. * * @param encryptedPart * The piece of data to decrypt and verify. * @return The intermediate result of the decryption; the decrypted data. Never returns {@code null}. * @exception PKCS11Exception * If decrypting or verifying the data failed. */ public byte[] decryptVerifyUpdate(byte[] encryptedPart) throws PKCS11Exception { final String method = "C_DecryptVerifyUpdate"; debugIn(method, "encryptedPart.length={}", len(encryptedPart)); try { return toNonNull(method, pkcs11.C_DecryptVerifyUpdate(sessionHandle, encryptedPart)); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * Generate a new secret key or a set of domain parameters. It uses the set attributes of the * template for setting the attributes of the new key object. As mechanism the application can use * a constant of the Mechanism class. * * @param mechanism * The mechanism to generate a key for; e.g. Mechanism.DES to generate a DES key. * @param template * The template for the new key or domain parameters; e.g. a DESSecretKey object which * has set certain attributes. * @return The newly generated secret key or domain parameters. * @exception PKCS11Exception * If generating a new secret key or domain parameters failed. */ public long generateKey(Mechanism mechanism, AttributeVector template) throws PKCS11Exception { final String method = "C_GenerateKey"; mechanism.setModule(module); debugIn(method, "mechanism={}, template={}", mechanism, template); try { long hKey = pkcs11.C_GenerateKey(sessionHandle, mechanism.toCkMechanism(), toOutCKAttributes(template), useUtf8); debugOut(method, "hKey={}", hKey); traceObject("generated key", hKey); return hKey; } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * Generate a new public key - private key key-pair and use the set attributes of the template * objects for setting the attributes of the new public key and private key objects. As mechanism * the application can use a constant of the Mechanism class. * * @param mechanism * The mechanism to generate a key for; e.g. Mechanism.RSA to generate a new RSA * key-pair. * @param template * The template for the new keypair. * @return The newly generated key-pair. * @exception PKCS11Exception * If generating a new key-pair failed. */ public PKCS11KeyPair generateKeyPair(Mechanism mechanism, KeyPairTemplate template) throws PKCS11Exception { final String method = "C_GenerateKeyPair"; mechanism.setModule(module); debugIn(method, "mechanism={}, template={}", mechanism, template); try { long[] objectHandles = pkcs11.C_GenerateKeyPair(sessionHandle, mechanism.toCkMechanism(), toOutCKAttributes(template.publicKey()), toOutCKAttributes(template.privateKey()), useUtf8); PKCS11KeyPair rv = new PKCS11KeyPair(objectHandles[0], objectHandles[1]); debugOut(method, "hPublicKey={}, hPrivateKey={}", rv.getPublicKey(), rv.getPrivateKey()); traceObject("public key of the generated keypair", rv.getPublicKey()); traceObject("private key of the generated keypair", rv.getPrivateKey()); return rv; } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * Wraps (encrypts) the given key with the wrapping key using the given mechanism. * * @param mechanism * The mechanism to use for wrapping the key. * @param wrappingKeyHandle * The key to use for wrapping (encrypting). * @param keyHandle * The key to wrap (encrypt). * @return The wrapped key as byte array. Never returns {@code null}. * @exception PKCS11Exception * If wrapping the key failed. */ public byte[] wrapKey(Mechanism mechanism, long wrappingKeyHandle, long keyHandle) throws PKCS11Exception { final String method = "C_WrapKey"; mechanism.setModule(module); debugIn(method, "wrappingKeyHandle={}, keyHandle={}, mechanism={}", wrappingKeyHandle, keyHandle, mechanism); try { return toNonNull(method, pkcs11.C_WrapKey(sessionHandle, mechanism.toCkMechanism(), wrappingKeyHandle, keyHandle, useUtf8)); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * Unwraps (decrypts) the given encrypted key with the unwrapping key using the given mechanism. * The application can also pass a template key to set certain attributes of the unwrapped key. * This creates a key object after unwrapping the key and returns an object representing this key. * * @param mechanism * The mechanism to use for unwrapping the key. * @param unwrappingKeyHandle * The key to use for unwrapping (decrypting). * @param wrappedKey * The encrypted key to unwrap (decrypt). * @param keyTemplate * The template for creating the new key object. * @return A key object representing the newly created key object. * @exception PKCS11Exception * If unwrapping the key or creating a new key object failed. */ public long unwrapKey(Mechanism mechanism, long unwrappingKeyHandle, byte[] wrappedKey, AttributeVector keyTemplate) throws PKCS11Exception { final String method = "C_UnwrapKey"; mechanism.setModule(module); debugIn(method, "unwrappingKeyHandle={}, wrappedKey.length={}, mechanism={}, template={}", unwrappingKeyHandle, len(wrappedKey), mechanism, keyTemplate); try { long hKey = pkcs11.C_UnwrapKey(sessionHandle, mechanism.toCkMechanism(), unwrappingKeyHandle, wrappedKey, toOutCKAttributes(keyTemplate), useUtf8); debugOut(method, "hKey={}", hKey); traceObject("unwrapped key", hKey); return hKey; } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * Derives a new key from a specified base key using the given mechanism. After deriving a new * key from the base key, a new key object is created and a representation of it is returned. The * application can provide a template key to set certain attributes of the new key object. * * @param mechanism * The mechanism to use for deriving the new key from the base key. * @param baseKeyHandle * The key to use as base for derivation. * @param template * The template for creating the new key object. * @return A key object representing the newly derived (created) key object or null, if the used * mechanism uses other means to return its values; e.g. the CKM_SSL3_KEY_AND_MAC_DERIVE * mechanism. * @exception PKCS11Exception * If deriving the key or creating a new key object failed. */ public long deriveKey(Mechanism mechanism, long baseKeyHandle, AttributeVector template) throws PKCS11Exception { final String method = "C_DeriveKey"; mechanism.setModule(module); debugIn(method, "baseKeyHandle={}, mechanism={}, template={}", baseKeyHandle, mechanism, template); try { long hKey = pkcs11.C_DeriveKey(sessionHandle, mechanism.toCkMechanism(), baseKeyHandle, toOutCKAttributes(template), useUtf8); debugOut(method, "hKey={}", hKey); traceObject("derived key", hKey); return hKey; } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * Mixes additional seeding material into the random number generator. * * @param seed * The seed bytes to mix in. * @exception PKCS11Exception * If mixing in the seed failed. */ public void seedRandom(byte[] seed) throws PKCS11Exception { try { pkcs11.C_SeedRandom(sessionHandle, seed); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { throw module.convertException(e); } } /** * Generates a certain number of random bytes. * * @param numberOfBytesToGenerate * The number of random bytes to generate. * @return An array of random bytes with length numberOfBytesToGenerate. * @exception PKCS11Exception * If generating random bytes failed. */ public byte[] generateRandom(int numberOfBytesToGenerate) throws PKCS11Exception { byte[] randomBytesBuffer = new byte[numberOfBytesToGenerate]; final String method = "C_GenerateRandom"; debugIn(method, "numberOfBytesToGenerate={}", numberOfBytesToGenerate); try { pkcs11.C_GenerateRandom(sessionHandle, randomBytesBuffer); return toNonNull(method, randomBytesBuffer); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { debugError(method, e); throw module.convertException(e); } } /** * Legacy function that will normally throw an PKCS11Exception with the error-code * CKR_FUNCTION_NOT_PARALLEL. * * @exception PKCS11Exception * Throws always a PKCS11Exception. */ public void getFunctionStatus() throws PKCS11Exception { try { pkcs11.C_GetFunctionStatus(sessionHandle); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { throw module.convertException(e); } } /** * Legacy function that will normally throw an PKCS11Exception with the error-code * CKR_FUNCTION_NOT_PARALLEL. * * @exception PKCS11Exception * Throws always a PKCS11Exception. */ public void cancelFunction() throws PKCS11Exception { try { pkcs11.C_CancelFunction(sessionHandle); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { throw module.convertException(e); } } /** * Determines if this session is an R/W session. * @return true if this is an R/W session, false otherwise. * @throws PKCS11Exception in case of error. */ public boolean isRwSession() throws PKCS11Exception { if (this.rwSession == null) { this.rwSession = getSessionInfo().isRwSession(); } return this.rwSession; } /** * Returns the string representation of this object. * * @return the string representation of this object */ @Override public String toString() { return "Session Handle: 0x" + Long.toHexString(sessionHandle) + "\nToken: " + token; } private Object toCkParameters(CkParams params) { return params == null ? null : params.getParams(); } public String getStringAttrValue(long objectHandle, long attributeType) throws PKCS11Exception { CharArrayAttribute attr = new CharArrayAttribute(attributeType); doGetAttrValue(objectHandle, attr); return attr.getValue(); } public AttributeVector getAttrValues(long objectHandle, long... attributeTypes) throws PKCS11Exception { List typeList = new ArrayList<>(attributeTypes.length); for (long attrType : attributeTypes) { typeList.add(attrType); } return getAttrValues(objectHandle, typeList); } public AttributeVector getAttrValues(long objectHandle, List attributeTypes) throws PKCS11Exception { if (attributeTypes.contains(CKA_EC_POINT) && !attributeTypes.contains(CKA_EC_PARAMS)) { synchronized (module) { Boolean b = module.getEcPointFixNeeded(); if (b == null || b) { attributeTypes.add(CKA_EC_PARAMS); } } } Attribute[] attrs = new Attribute[attributeTypes.size()]; int index = 0; // we need to fix attributes EC_PARAMS and EC_POINT. Where EC_POINT needs EC_PARAMS, // and EC_PARAMS needs KEY_TYPE. long[] firstTypes = {CKA_CLASS, CKA_KEY_TYPE, CKA_EC_PARAMS, CKA_EC_POINT}; for (long type : firstTypes) { if (attributeTypes.remove(type)) { attrs[index++] = Attribute.getInstance(type); } } for (long type : attributeTypes) { attrs[index++] = Attribute.getInstance(type); } doGetAttrValues(objectHandle, attrs); return new AttributeVector(attrs); } /** * Return the default attributes, but without attributes which contain the sensitive values. * @param objectHandle the object handle. * @return the attributes. * @throws PKCS11Exception If getting attributes failed. */ public AttributeVector getDefaultAttrValues(long objectHandle) throws PKCS11Exception { return getDefaultAttrValues(objectHandle, false); } /** * Return the default attributes * @param objectHandle the object handle. * @param withSensitiveVAttributes whether to get the attributes which contain sensitive values. * @return the attributes. * @throws PKCS11Exception If getting attributes failed. */ public AttributeVector getDefaultAttrValues(long objectHandle, boolean withSensitiveVAttributes) throws PKCS11Exception { long objClass = getAttrValues(objectHandle, CKA_CLASS).class_(); List ckaTypes = new LinkedList<>(); addCkaTypes(ckaTypes, CKA_LABEL, CKA_ID, CKA_TOKEN); if (objClass == CKO_SECRET_KEY || objClass == CKO_PRIVATE_KEY) { addCkaTypes(ckaTypes, CKA_ALLOWED_MECHANISMS, CKA_DECRYPT, CKA_DERIVE, CKA_EXTRACTABLE, CKA_KEY_GEN_MECHANISM, CKA_NEVER_EXTRACTABLE, CKA_PRIVATE, CKA_SIGN, CKA_UNWRAP, CKA_UNWRAP_TEMPLATE, CKA_WRAP_WITH_TRUSTED); AttributeVector attrs = getAttrValues(objectHandle, CKA_KEY_TYPE, CKA_SENSITIVE, CKA_ALWAYS_SENSITIVE); long keyType = attrs.keyType(); Boolean sensitive = attrs.sensitive(); Boolean alwaysSensitive = attrs.alwaysSensitive(); boolean withSensitiveAttrs = withSensitiveVAttributes; if (withSensitiveAttrs) { boolean isSensitive = (sensitive == null) || sensitive; if (alwaysSensitive != null) { isSensitive |= alwaysSensitive; } withSensitiveAttrs = !isSensitive; } if (objClass == CKO_SECRET_KEY) { addCkaTypes(ckaTypes, CKA_ENCRYPT, CKA_TRUSTED, CKA_VERIFY, CKA_WRAP, CKA_WRAP_TEMPLATE); if (!(keyType == CKK_DES || keyType == CKK_DES2 || keyType == CKK_DES3)) { ckaTypes.add(CKA_VALUE_LEN); } if (withSensitiveAttrs) { ckaTypes.add(CKA_VALUE); } } else { addCkaTypes(ckaTypes, CKA_ALWAYS_AUTHENTICATE, CKA_SIGN_RECOVER); if (keyType == CKK_RSA) { addCkaTypes(ckaTypes, CKA_MODULUS, CKA_PUBLIC_EXPONENT); if (withSensitiveAttrs) { addCkaTypes(ckaTypes, CKA_PRIVATE_EXPONENT, CKA_PRIME_1, CKA_PRIME_2, CKA_EXPONENT_1, CKA_EXPONENT_2, CKA_COEFFICIENT); } } else if (keyType == CKK_EC || keyType == CKK_EC_EDWARDS || keyType == CKK_EC_MONTGOMERY || keyType == CKK_VENDOR_SM2) { ckaTypes.add(CKA_EC_PARAMS); if (withSensitiveAttrs) { ckaTypes.add(CKA_VALUE); } } else if (keyType == CKK_DSA) { addCkaTypes(ckaTypes, CKA_PRIME, CKA_SUBPRIME, CKA_BASE); if (withSensitiveAttrs) { ckaTypes.add(CKA_VALUE); } } } return getAttrValues(objectHandle, ckaTypes).class_(objClass).keyType(keyType) .sensitive(sensitive).alwaysSensitive(alwaysSensitive); } else if (objClass == CKO_PUBLIC_KEY) { addCkaTypes(ckaTypes, CKA_ALLOWED_MECHANISMS, CKA_ENCRYPT, CKA_KEY_GEN_MECHANISM, CKA_TRUSTED, CKA_VERIFY, CKA_VERIFY_RECOVER, CKA_WRAP, CKA_WRAP_TEMPLATE); long keyType = getAttrValues(objectHandle, CKA_KEY_TYPE).keyType(); if (keyType == CKK_RSA) { addCkaTypes(ckaTypes, CKA_MODULUS, CKA_PUBLIC_EXPONENT); } else if (keyType == CKK_EC || keyType == CKK_EC_EDWARDS || keyType == CKK_EC_MONTGOMERY || keyType == CKK_VENDOR_SM2) { addCkaTypes(ckaTypes, CKA_EC_PARAMS, CKA_EC_POINT); } else if (keyType == CKK_DSA) { addCkaTypes(ckaTypes, CKA_PRIME, CKA_SUBPRIME, CKA_BASE); } return getAttrValues(objectHandle, ckaTypes).class_(objClass).keyType(keyType); } else if (objClass == CKO_CERTIFICATE) { addCkaTypes(ckaTypes, CKA_TRUSTED, CKA_CERTIFICATE_CATEGORY, CKA_START_DATE, CKA_END_DATE); long certType = getAttrValues(objectHandle, CKA_CERTIFICATE_TYPE).certificateType(); if (certType == CKC_X_509) { addCkaTypes(ckaTypes, CKA_VALUE, CKA_URL, CKA_ISSUER, CKA_SUBJECT, CKA_SERIAL_NUMBER, CKA_HASH_OF_ISSUER_PUBLIC_KEY, CKA_HASH_OF_SUBJECT_PUBLIC_KEY); } return getAttrValues(objectHandle, ckaTypes).class_(objClass).certificateType(certType); } else { return getAttrValues(objectHandle, ckaTypes); } } private static void addCkaTypes(List list, long... types) { for (long type : types) { list.add(type); } } /** * This method reads the attributes at once. This can lead to performance * improvements. If reading all attributes at once fails, it tries to read * each attributes individually. * * @param objectHandle * The handle of the object which contains the attributes. * @param attributes * The objects specifying the attribute types * (see {@link Attribute#getType()}) and receiving the attribute * values (see {@link Attribute#ckAttribute(CK_ATTRIBUTE)}). * @exception PKCS11Exception * If getting the attributes failed. */ private void doGetAttrValues(long objectHandle, Attribute... attributes) throws PKCS11Exception { Functions.requireNonNull("attributes", attributes); if (attributes.length == 1) { doGetAttrValue(objectHandle, attributes[0]); return; } CK_ATTRIBUTE[] attributeTemplateList = new CK_ATTRIBUTE[attributes.length]; for (int i = 0; i < attributes.length; i++) { attributeTemplateList[i] = new CK_ATTRIBUTE(); attributeTemplateList[i].type = attributes[i].getType(); } PKCS11Exception delayedEx = null; try { pkcs11.C_GetAttributeValue(sessionHandle, objectHandle, attributeTemplateList, useUtf8); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception ex) { delayedEx = module.convertException(ex); } for (int i = 0; i < attributes.length; i++) { Attribute attribute = attributes[i]; CK_ATTRIBUTE template = attributeTemplateList[i]; if (template != null) { attribute.present(true).sensitive(false).ckAttribute(template); } } if (delayedEx != null) { // do all failed separately again. delayedEx = null; for (Attribute attr : attributes) { if (attr.getCkAttribute() == null || attr.getCkAttribute().pValue == null) { try { doGetAttrValue0(objectHandle, attr, false); } catch (PKCS11Exception ex) { if (delayedEx == null) { delayedEx = ex; } } } } } for (Attribute attr : attributes) { postProcessGetAttribute(attr, objectHandle, attributes); } if (delayedEx != null) { throw delayedEx; } } /** * This method reads the attribute specified by attribute from * the token using the given session. * The object from which to read the attribute is specified using the * objectHandle. The attribute will contain * the results. * If the attempt to read the attribute returns * CKR_ATTRIBUTE_TYPE_INVALID, this will be indicated by * setting {@link Attribute#present(boolean)} to false. * It CKR_ATTRIBUTE_SENSITIVE is returned, the attribute object is * marked as present * (by calling {@link Attribute#present(boolean)} with * true), and in addition as sensitive by calling * {@link Attribute#sensitive(boolean)} with true. * * @param objectHandle * The handle of the object which contains the attribute. * @param attribute * The object specifying the attribute type * (see {@link Attribute#getType()}) and receiving the attribute * value (see {@link Attribute#ckAttribute(CK_ATTRIBUTE)}). * @exception PKCS11Exception * If getting the attribute failed. */ private void doGetAttrValue(long objectHandle, Attribute attribute) throws PKCS11Exception { if (attribute.getType() == CKA_EC_POINT) { Boolean b = module.getEcPointFixNeeded(); if ((b == null || b)) { doGetAttrValues(objectHandle, new ByteArrayAttribute(CKA_EC_PARAMS), attribute); return; } } doGetAttrValue0(objectHandle, attribute, true); } private void doGetAttrValue0(long objectHandle, Attribute attribute, boolean postProcess) throws PKCS11Exception { attribute.present(false); try { CK_ATTRIBUTE[] attributeTemplateList = new CK_ATTRIBUTE[1]; attributeTemplateList[0] = new CK_ATTRIBUTE(); attributeTemplateList[0].type = attribute.getType(); // attributeTemplateList[0].pValue; pkcs11.C_GetAttributeValue(sessionHandle, objectHandle, attributeTemplateList, useUtf8); attribute.ckAttribute(attributeTemplateList[0]).present(true).sensitive(false); } catch (iaik.pkcs.pkcs11.wrapper.PKCS11Exception ex) { long ec = ex.getErrorCode(); if (ec == CKR_ATTRIBUTE_TYPE_INVALID) { if (attribute.getType() == CKA_EC_PARAMS) { // this means, that some requested attributes are missing, but // we can ignore this and proceed; e.g. a v2.01 module won't // have the object ID attribute attribute.present(false).getCkAttribute().pValue = null; } } else if (ec == CKR_ATTRIBUTE_SENSITIVE) { // this means, that some requested attributes are missing, but // we can ignore this and proceed; e.g. a v2.01 module won't // have the object ID attribute attribute.getCkAttribute().pValue = null; attribute.present(true).sensitive(true).getCkAttribute().pValue = null; } else if (ec == CKR_ARGUMENTS_BAD || ec == CKR_FUNCTION_FAILED || ec == CKR_FUNCTION_REJECTED) { attribute.present(false).sensitive(false).getCkAttribute().pValue = null; } else { // there was a different error that we should propagate throw module.convertException(ex); } } if (postProcess) { postProcessGetAttribute(attribute, objectHandle); } } private CK_ATTRIBUTE[] toOutCKAttributes(AttributeVector template) { return toOutCKAttributes(template, false); } private CK_ATTRIBUTE[] toOutCKAttributes(AttributeVector template, boolean withoutNullValueAttr) { if (template == null) { return null; } CK_ATTRIBUTE[] ckAttrs = template.toCkAttributes(); List nonNullCkAttrs = null; if (withoutNullValueAttr) { nonNullCkAttrs = new ArrayList<>(ckAttrs.length); } for (CK_ATTRIBUTE ckAttr : ckAttrs) { if (ckAttr.pValue == null) { continue; } else { if (withoutNullValueAttr) { nonNullCkAttrs.add(ckAttr); } } if (ckAttr.type == CKA_KEY_TYPE) { long value = (long) ckAttr.pValue; ckAttr.pValue = module.genericToVendorCode(Category.CKK, value); } else if (ckAttr.type == CKA_EC_POINT) { ckAttr.pValue = Functions.toOctetString((byte[]) ckAttr.pValue); } } return nonNullCkAttrs != null && nonNullCkAttrs.size() != ckAttrs.length ? nonNullCkAttrs.toArray(new CK_ATTRIBUTE[0]) : ckAttrs; } private void postProcessGetAttribute(Attribute attr, long objectHandle, Attribute... otherAttrs) { long type = attr.getType(); CK_ATTRIBUTE ckAttr = attr.getCkAttribute(); if (type == CKA_EC_PARAMS) { if (ckAttr.pValue == null) { // Some HSMs do not return EC_PARAMS Long keyType = null; if (otherAttrs != null) { for (Attribute otherAttr : otherAttrs) { if (otherAttr.type() == CKA_KEY_TYPE) { keyType = ((LongAttribute) otherAttr).getValue(); } } } if (keyType == null) { try { keyType = getAttrValues(objectHandle, CKA_KEY_TYPE).keyType(); } catch (PKCS11Exception e2) { } } if (keyType != null && keyType == CKK_VENDOR_SM2) { attr.present(false).getCkAttribute().pValue = Functions.decodeHex("06082a811ccf5501822d"); } } else { byte[] ecParams = (byte[]) ckAttr.pValue; if (ecParams[0] != 0x06) { // 06: OBJECT IDENTIFIER ckAttr.pValue = Functions.fixECParams((byte[]) ckAttr.pValue); } } return; } if (ckAttr == null || ckAttr.pValue == null) { return; } if (type == CKA_KEY_TYPE) { long value = (long) ckAttr.pValue; if (!isUnavailableInformation(value)) { ckAttr.pValue = module.vendorToGenericCode(Category.CKK, value); } } else if (type == CKA_KEY_GEN_MECHANISM) { long value = (long) ckAttr.pValue; if (!isUnavailableInformation(value)) { ckAttr.pValue = module.vendorToGenericCode(Category.CKM, value); } } else if (type == CKA_ALLOWED_MECHANISMS) { long[] mechanisms = ((MechanismArrayAttribute) attr).getValue(); for (long mech : mechanisms) { ckAttr.pValue = module.vendorToGenericCode(Category.CKM, mech); } } else if (type == CKA_EC_POINT) { Boolean b = module.getEcPointFixNeeded(); byte[] pValue = (byte[]) ckAttr.pValue; if (b == null || b) { byte[] ecParams = null; if (otherAttrs != null) { for (Attribute otherAttr : otherAttrs) { if (otherAttr.getType() == CKA_EC_PARAMS) { ecParams = ((ByteArrayAttribute) otherAttr).getValue(); break; } } } byte[] fixedCoreEcPoint = Functions.getCoreECPoint(pValue, ecParams); if (b == null) { byte[] coreEcPoint = Functions.getCoreECPoint(pValue); module.setEcPointFixNeeded(!Arrays.equals(coreEcPoint, fixedCoreEcPoint)); } ckAttr.pValue = fixedCoreEcPoint; } else { ckAttr.pValue = Functions.getCoreECPoint(pValue); } } else if (attr instanceof BooleanAttribute) { if (ckAttr.pValue instanceof byte[]) { byte[] value = (byte[]) ckAttr.pValue; boolean allZeros = true; for (byte b : value) { if (b != 0) { allZeros = false; break; } } ckAttr.pValue = !allZeros; } } } private void debugIn(String method) { if (StaticLogger.isDebugEnabled()) { StaticLogger.debug("IN " + method + ": hSession=" + sessionHandle); } } private void debugIn(String method, String format, Object... arguments) { if (StaticLogger.isDebugEnabled()) { StaticLogger.debug("IN " + method + ": hSession=" + sessionHandle + ", " + format, arguments); } } private void debugOut(String method) { if (StaticLogger.isDebugEnabled()) { StaticLogger.debug("OUT " + method + ": hSession=" + sessionHandle); } } private void debugOut(String method, String format, Object... arguments) { if (StaticLogger.isDebugEnabled()) { StaticLogger.debug("OUT " + method + ": hSession=" + sessionHandle + ", " + format, arguments); } } private void debugError(String method, iaik.pkcs.pkcs11.wrapper.PKCS11Exception e) { if (StaticLogger.isDebugEnabled()) { StaticLogger.debug("ERR " + method + ": " + module.codeToName(Category.CKR, e.getErrorCode())); } } private void setModule(CkParams params) { if (params != null) { params.setModule(module); } } private static int len(byte[] bytes) { return bytes == null ? 0 : bytes.length; } private byte[] toNonNull(String method, byte[] bytes) { if (bytes == null) { debugOut(method, "rv=null"); } else { debugOut(method, "rv.length={}", bytes.length); } return (bytes == null) ? new byte[0] : bytes; } private byte[] toNonNull(byte[] bytes) { return (bytes == null) ? new byte[0] : bytes; } private void traceObject(String prefix, long hObject) { if (StaticLogger.isTraceEnabled()) { try { StaticLogger.trace(prefix + ": handle=" + hObject + ", attributes\n" + getDefaultAttrValues(hObject)); } catch (PKCS11Exception e) { StaticLogger.trace(prefix + ": reading object " + hObject + " failed with " + e.getErrorName()); } } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy