Skip to content

Commit 5ce2461

Browse files
author
Mohit
committed
Merge branch 'dev' into mchand/proguard-rules
2 parents 53bb836 + bb4d8e9 commit 5ce2461

2 files changed

Lines changed: 79 additions & 3 deletions

File tree

common/src/main/java/com/microsoft/identity/common/internal/util/AndroidKeyStoreUtil.java

Lines changed: 69 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555

5656
import edu.umd.cs.findbugs.annotations.Nullable;
5757
import io.opentelemetry.api.common.Attributes;
58+
import io.opentelemetry.api.common.AttributesBuilder;
5859
import io.opentelemetry.api.metrics.LongCounter;
5960
import lombok.NonNull;
6061

@@ -84,6 +85,11 @@ public class AndroidKeyStoreUtil {
8485
*/
8586
private static final String ANDROID_KEY_STORE_TYPE = "AndroidKeyStore";
8687

88+
/**
89+
* Max length of stack trace to search for a keystore exception
90+
*/
91+
private static int KEYSTORE_EXCEPTION_CAUSE_CHAIN_MAX_DEPTH = 20;
92+
8793
private AndroidKeyStoreUtil() {
8894
}
8995

@@ -447,12 +453,11 @@ public static synchronized SecretKey unwrap(@NonNull final byte[] wrappedKeyBlob
447453
exception
448454
);
449455
if (exception instanceof InvalidKeyException) {
450-
final Attributes attributes = Attributes.builder()
456+
final Attributes attributes = createAttributesBuilderFromInvalidKeyException((InvalidKeyException) exception)
451457
.put(AttributeName.keystore_operation.name(), "unwrap")
452458
.put(AttributeName.error_code.name(), errCode)
453-
.put(AttributeName.error_type.name(), clientException.getClass().getSimpleName())
454-
.put(AttributeName.keystore_exception_stack_trace.name(), ThrowableUtil.getStackTraceAsString(clientException))
455459
.build();
460+
456461
sFailedAndroidKeyStoreUnwrapOperationCount.add(1, attributes);
457462
}
458463
Logger.error(
@@ -464,4 +469,65 @@ public static synchronized SecretKey unwrap(@NonNull final byte[] wrappedKeyBlob
464469
throw clientException;
465470
}
466471

472+
/**
473+
* Populate attributes from an InvalidKeyException, attempting to extract details from a nested
474+
* KeyStoreException if available (API Level 33+).
475+
*/
476+
private static AttributesBuilder createAttributesBuilderFromInvalidKeyException(final InvalidKeyException exception) {
477+
String ksMessage;
478+
final String errorType;
479+
final String ksNumericErrorCode;
480+
481+
// Check API Level before attempting to extract KeyStoreException details
482+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
483+
final android.security.KeyStoreException keyStoreException = findKeyStoreException(exception);
484+
if (keyStoreException != null) {
485+
ksMessage = keyStoreException.getMessage();
486+
if (ksMessage == null) {
487+
ksMessage = "Keystore exception found, no error message";
488+
}
489+
errorType = "KeyStoreException";
490+
ksNumericErrorCode = String.valueOf(keyStoreException.getNumericErrorCode());
491+
} else {
492+
ksMessage = "No keystore exception found";
493+
errorType = "InvalidKeyException";
494+
ksNumericErrorCode = "";
495+
}
496+
} else {
497+
ksMessage = "API Level below 33, keystore exception not available";
498+
errorType = "InvalidKeyException";
499+
ksNumericErrorCode = "";
500+
}
501+
502+
return Attributes.builder()
503+
.put(AttributeName.error_type.name(), errorType)
504+
.put(AttributeName.keystore_exception_stack_trace.name(), ThrowableUtil.getStackTraceAsString(exception))
505+
.put(AttributeName.keystore_exception_message.name(), ksMessage)
506+
.put(AttributeName.keystore_numeric_error_code.name(), ksNumericErrorCode);
507+
}
508+
509+
/**
510+
* Searches the causal chain of the given throwable for an instance of
511+
* {@link android.security.KeyStoreException}.
512+
*
513+
* @param throwable The throwable to search.
514+
* @return The found KeyStoreException, or null if none was found or the API level is below 33.
515+
*/
516+
private static @Nullable android.security.KeyStoreException findKeyStoreException(@NonNull Throwable throwable) {
517+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
518+
// Check up to a max depth to avoid infinite loops in case of circular references
519+
int count = 0;
520+
while (throwable != null && count < KEYSTORE_EXCEPTION_CAUSE_CHAIN_MAX_DEPTH) {
521+
if (throwable instanceof android.security.KeyStoreException) {
522+
return (android.security.KeyStoreException) throwable;
523+
}
524+
throwable = throwable.getCause();
525+
count++;
526+
}
527+
528+
return null;
529+
} else {
530+
return null;
531+
}
532+
}
467533
}

common4j/src/main/com/microsoft/identity/common/java/opentelemetry/AttributeName.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,16 @@ public enum AttributeName {
305305
*/
306306
keystore_exception_stack_trace,
307307

308+
/**
309+
* Indicates the exception message from a Android KeyStore operation exception.
310+
*/
311+
keystore_exception_message,
312+
313+
/**
314+
* Indicates the error code from a Android KeyStore operation exception.
315+
*/
316+
keystore_numeric_error_code,
317+
308318
/**
309319
* Indicates the new nonce found in the eSTS request.
310320
*/

0 commit comments

Comments
 (0)