1212import eu .europa .esig .dss .token .DSSPrivateKeyEntry ;
1313import eu .europa .esig .dss .token .KSPrivateKeyEntry ;
1414import eu .europa .esig .dss .token .Pkcs11SignatureToken ;
15- import sun .security .pkcs11 .wrapper .CK_ATTRIBUTE ;
16- import sun .security .pkcs11 .wrapper .PKCS11 ;
17- import sun .security .pkcs11 .wrapper .PKCS11Constants ;
18- import sun .security .pkcs11 .wrapper .PKCS11Exception ;
1915
16+ import java .lang .reflect .Array ;
2017import java .lang .reflect .Field ;
18+ import java .lang .reflect .InvocationTargetException ;
19+ import java .lang .reflect .Method ;
2120import java .security .GeneralSecurityException ;
2221import java .security .PrivateKey ;
2322import java .security .Signature ;
2625
2726public class NativePkcs11SignatureToken extends Pkcs11SignatureToken {
2827 private static final long CKU_CONTEXT_SPECIFIC = 2L ;
28+ private static final String PKCS11_EXCEPTION_CLASS_NAME = "sun.security.pkcs11.wrapper.PKCS11Exception" ;
29+ private static final String PKCS11_CONSTANTS_CLASS_NAME = "sun.security.pkcs11.wrapper.PKCS11Constants" ;
30+ private static final String CK_ATTRIBUTE_CLASS_NAME = "sun.security.pkcs11.wrapper.CK_ATTRIBUTE" ;
31+
2932 private final PasswordManager passwordManager ;
3033 private final SignatureTokenSettings settings ;
3134
@@ -60,44 +63,51 @@ private void runContextSpecificLoginIfNeeded(Signature signature, PrivateKey pk)
6063
6164 if (isAlwaysAuthenticate (p11 , sessionId , pk ) && (settings .getForceContextSpecificLoginEnabled () || !isProtectedAuthenticationPath (p11 , getSlotListIndex ()))) {
6265 var password = passwordManager .getContextSpecificPassword ();
63- if (password == null ) throw new PasswordNotProvidedException (); // handle password not provided
64- p11 . C_Login ( sessionId , CKU_CONTEXT_SPECIFIC , password );
66+ if (password == null ) throw new PasswordNotProvidedException ();
67+ invokeCLogin ( p11 , sessionId , CKU_CONTEXT_SPECIFIC , password );
6568 }
6669 } catch (AutogramException e ) {
67- throw e ; // rethrow autogram errors
68- } catch (PKCS11Exception e ) {
69- if (e .getMessage ().equals ("CKR_PIN_INCORRECT" ))
70- throw new PINIncorrectException ();
71-
72- throw new GeneralSecurityException (e );
70+ throw e ;
71+ } catch (Exception e ) {
72+ var cause = unwrapInvocationException (e );
73+ if (isPkcs11Exception (cause )) {
74+ if ("CKR_PIN_INCORRECT" .equals (cause .getMessage ())) {
75+ throw new PINIncorrectException ();
76+ }
77+ throw new GeneralSecurityException (cause );
78+ }
79+ throw new GeneralSecurityException (cause );
7380 }
7481 }
7582
76- private static boolean isAlwaysAuthenticate (PKCS11 p11 , long sessionId , PrivateKey pk ) throws PKCS11Exception {
83+ private static boolean isAlwaysAuthenticate (Object p11 , long sessionId , PrivateKey pk ) throws Exception {
7784 var keyID = getKeyID (pk );
78- var attrs = new CK_ATTRIBUTE []{ new CK_ATTRIBUTE ( PKCS11Constants . CKA_ALWAYS_AUTHENTICATE )} ;
85+ var attrs = newAttributeArray ( getPkcs11Constant ( " CKA_ALWAYS_AUTHENTICATE" )) ;
7986
80- p11 . C_GetAttributeValue ( sessionId , keyID , attrs );
87+ invokeCGetAttributeValue ( p11 , sessionId , keyID , attrs );
8188
82- var result = attrs [0 ].pValue ;
89+ var attr = Array .get (attrs , 0 );
90+ var result = getPublicField (attr , "pValue" );
8391 if (result instanceof byte []) {
8492 return ((byte []) result )[0 ] == 1 ;
85- } else {
86- return false ; // CKA_ALWAYS_AUTHENTICATE not found
8793 }
94+ return false ;
8895 }
8996
90- private static boolean isProtectedAuthenticationPath (PKCS11 p11 , int slotIndex ) throws PKCS11Exception {
91-
92- var slotList = p11 .C_GetSlotList (false );
93- if (slotList .length <= slotIndex || slotList .length < 1 )
97+ private static boolean isProtectedAuthenticationPath (Object p11 , int slotIndex ) throws Exception {
98+ var slotList = invokeCGetSlotList (p11 , false );
99+ if (slotList .length <= slotIndex || slotList .length < 1 ) {
94100 return false ;
101+ }
95102
96- if (slotIndex < 0 )
103+ if (slotIndex < 0 ) {
97104 slotIndex = 0 ;
105+ }
98106
99107 var slotId = slotList [slotIndex ];
100- return (p11 .C_GetTokenInfo (slotId ).flags & PKCS11Constants .CKF_PROTECTED_AUTHENTICATION_PATH ) != 0 ;
108+ var tokenInfo = invokeCGetTokenInfo (p11 , slotId );
109+ var flags = (long ) getPublicField (tokenInfo , "flags" );
110+ return (flags & getPkcs11Constant ("CKF_PROTECTED_AUTHENTICATION_PATH" )) != 0 ;
101111 }
102112
103113 private int getSlotListIndex () {
@@ -145,7 +155,7 @@ private static long getSessionId(Signature signature) {
145155 }
146156 }
147157
148- private static PKCS11 getP11 (Signature signature ) {
158+ private static Object getP11 (Signature signature ) {
149159 try {
150160 Field sigSpiField = signature .getClass ().getDeclaredField ("sigSpi" );
151161 sigSpiField .setAccessible (true );
@@ -157,14 +167,73 @@ private static PKCS11 getP11(Signature signature) {
157167
158168 var p11Field = token .getClass ().getDeclaredField ("p11" );
159169 p11Field .setAccessible (true );
160- var p11 = p11Field .get (token );
161-
162- return (PKCS11 ) p11 ;
170+ return p11Field .get (token );
163171 } catch (NoSuchFieldException | IllegalAccessException e ) {
164172 throw new RuntimeException (e );
165173 }
166174 }
167175
176+ private static Object newAttributeArray (long attributeType ) throws Exception {
177+ var attrClass = Class .forName (CK_ATTRIBUTE_CLASS_NAME );
178+ var array = Array .newInstance (attrClass , 1 );
179+ var attribute = attrClass .getConstructor (long .class ).newInstance (attributeType );
180+ Array .set (array , 0 , attribute );
181+ return array ;
182+ }
183+
184+ private static long getPkcs11Constant (String fieldName ) throws Exception {
185+ return Class .forName (PKCS11_CONSTANTS_CLASS_NAME ).getField (fieldName ).getLong (null );
186+ }
187+
188+ private static void invokeCLogin (Object p11 , long sessionId , long userType , char [] pin ) throws Exception {
189+ invokeMethod (p11 , "C_Login" , new Class <?>[]{long .class , long .class , char [].class }, sessionId , userType , pin );
190+ }
191+
192+ private static void invokeCGetAttributeValue (Object p11 , long sessionId , long objectHandle , Object attrs ) throws Exception {
193+ invokeMethod (p11 , "C_GetAttributeValue" , new Class <?>[]{long .class , long .class , attrs .getClass ()}, sessionId , objectHandle , attrs );
194+ }
195+
196+ private static long [] invokeCGetSlotList (Object p11 , boolean tokenPresent ) throws Exception {
197+ return (long []) invokeMethod (p11 , "C_GetSlotList" , new Class <?>[]{boolean .class }, tokenPresent );
198+ }
199+
200+ private static Object invokeCGetTokenInfo (Object p11 , long slotId ) throws Exception {
201+ return invokeMethod (p11 , "C_GetTokenInfo" , new Class <?>[]{long .class }, slotId );
202+ }
203+
204+ private static Object invokeMethod (Object target , String methodName , Class <?>[] parameterTypes , Object ... args ) throws Exception {
205+ Method method = target .getClass ().getMethod (methodName , parameterTypes );
206+ try {
207+ return method .invoke (target , args );
208+ } catch (InvocationTargetException e ) {
209+ var cause = unwrapInvocationException (e );
210+ if (cause instanceof Exception exception ) {
211+ throw exception ;
212+ }
213+ throw new RuntimeException (cause );
214+ }
215+ }
216+
217+ private static Object getPublicField (Object target , String fieldName ) {
218+ try {
219+ Field field = target .getClass ().getField (fieldName );
220+ return field .get (target );
221+ } catch (ReflectiveOperationException e ) {
222+ throw new RuntimeException (e );
223+ }
224+ }
225+
226+ private static Throwable unwrapInvocationException (Throwable throwable ) {
227+ if (throwable instanceof InvocationTargetException invocationTargetException && invocationTargetException .getCause () != null ) {
228+ return invocationTargetException .getCause ();
229+ }
230+ return throwable ;
231+ }
232+
233+ private static boolean isPkcs11Exception (Throwable throwable ) {
234+ return throwable != null && PKCS11_EXCEPTION_CLASS_NAME .equals (throwable .getClass ().getName ());
235+ }
236+
168237 // mostly copy & paste just to call overridden private sign method
169238 @ Override
170239 public SignatureValue sign (ToBeSigned toBeSigned , SignatureAlgorithm signatureAlgorithm , DSSPrivateKeyEntry keyEntry ) throws DSSException {
0 commit comments