@@ -450,17 +450,26 @@ public static synchronized SecretKey unwrap(@NonNull final byte[] wrappedKeyBlob
450450 );
451451 if (exception instanceof InvalidKeyException ) {
452452 final android .security .KeyStoreException keyStoreException = findKeyStoreException (exception );
453- String ksMessage = keyStoreException != null ? keyStoreException .getMessage () : "No Keystore Exception Found" ;
454- if (ksMessage == null ) {
455- ksMessage = "" ;
453+ String ksMessage ;
454+ final String ksNumericErrorCode ;
455+ if (keyStoreException != null ) {
456+ ksMessage = keyStoreException .getMessage ();
457+ if (ksMessage == null ) {
458+ ksMessage = "" ;
459+ }
460+ ksNumericErrorCode = getNumericErrorCodeFromKeyStoreException (keyStoreException );
461+ } else {
462+ ksMessage = "No Keystore Exception Found" ;
463+ ksNumericErrorCode = "" ;
456464 }
465+
457466 final Attributes attributes = Attributes .builder ()
458467 .put (AttributeName .keystore_operation .name (), "unwrap" )
459468 .put (AttributeName .error_code .name (), errCode )
460469 .put (AttributeName .error_type .name (), clientException .getClass ().getSimpleName ())
461470 .put (AttributeName .keystore_exception_stack_trace .name (), ThrowableUtil .getStackTraceAsString (clientException ))
462471 .put (AttributeName .keystore_exception_message .name (), ksMessage )
463- .put (AttributeName .keystore_internal_error_code .name (), extractInternalKeystoreCode ( ksMessage ) )
472+ .put (AttributeName .keystore_internal_error_code .name (), ksNumericErrorCode )
464473 .build ();
465474 sFailedAndroidKeyStoreUnwrapOperationCount .add (1 , attributes );
466475 }
@@ -473,7 +482,13 @@ public static synchronized SecretKey unwrap(@NonNull final byte[] wrappedKeyBlob
473482 throw clientException ;
474483 }
475484
476-
485+ /**
486+ * Searches the causal chain of the given throwable for an instance of
487+ * {@link android.security.KeyStoreException}.
488+ *
489+ * @param throwable The throwable to search.
490+ * @return The found KeyStoreException, or null if none was found or the API level is below 33.
491+ */
477492 private static @ Nullable android .security .KeyStoreException findKeyStoreException (@ NonNull Throwable throwable ) {
478493 if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .TIRAMISU ) {
479494 while (throwable != null ) {
@@ -489,14 +504,16 @@ public static synchronized SecretKey unwrap(@NonNull final byte[] wrappedKeyBlob
489504 }
490505
491506 /**
492- * Use Regex to pull out the internal error code from the key store exception message
493- * @param message the exception message
494- * @return the internal error code, or "N/A" if it can't be found
507+ * Extracts the numeric error code from a KeyStoreException if available.
508+ *
509+ * @param exception The KeyStoreException from which to extract the error code.
510+ * @return The numeric error code as a String, or an empty string if not available.
495511 */
496- private static String extractInternalKeystoreCode (final String message ) {
497- if (message == null ) return "" ;
498- Pattern pattern = Pattern .compile ("internal Keystore code:\\ s*(-?\\ d+)" );
499- Matcher matcher = pattern .matcher (message );
500- return matcher .find () ? matcher .group (1 ) : "" ;
512+ private static String getNumericErrorCodeFromKeyStoreException (@ NonNull android .security .KeyStoreException exception ) {
513+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .TIRAMISU ) {
514+ return String .valueOf (exception .getNumericErrorCode ());
515+ } else {
516+ return "" ;
517+ }
501518 }
502519}
0 commit comments