UNPKG

@nevis-security/nevis-mobile-authentication-sdk-react

Version:

React Native plugin for Nevis Mobile Authentication SDK. Supports only mobile.

353 lines (326 loc) 14.3 kB
/** * Copyright © 2025 Nevis Security AG. All rights reserved. */ import type { CertificateChainValidationResult } from './CertificateChainValidationResult'; import type { SecurityLevel } from './SecurityLevel'; enum FidoUafAttestationInformationType { OnlySurrogateBasicSupported, OnlyDefaultMode, StrictMode, StrictStrongBoxMode, } /** * The interface informing about whether the device supports {@link https://docs.nevis.net/configurationguide/mobile-auth-concept-and-integration-guide/use-cases-and-best-practices/uaf-surrogate-full-basic-comparison | Full Basic Attestations}. * * If full basic is required by the backend during registration, and this device does not support it, * registration will fail. This information can be used to preemptively inform the user that the device * is not supported. * * Note that it is guaranteed that the only type of instances that the {@link AndroidDeviceCapabilities.fidoUafAttestationInformationGetter} * returns are either {@link OnlySurrogateBasicSupported}, {@link OnlyDefaultMode}, {@link StrictMode} or {@link StrictStrongBoxMode}. * * @see * - {@link MobileAuthenticationClient.deviceCapabilities} * - {@link AndroidDeviceCapabilities.fidoUafAttestationInformationGetter} * - {@link FidoUafAttestationInformationGetter} */ export abstract class FidoUafAttestationInformation { /** * The {@link SecurityLevel} of the environment where the FIDO UAF keys are stored. * This provides information about the security of the environment where the keys are stored. */ abstract keymasterSecurityLevel: SecurityLevel; /** * The {@link https://source.android.com/docs/security/features/keystore/attestation#keydescription-fields | keymaster} version. */ abstract keymasterVersion: number; /** * Returns `true` if the {@link https://source.android.com/docs/security/features/keystore/attestation#rootoftrust-fields | device's bootloader} * is locked, and `false` otherwise. */ abstract isDeviceBootloaderLocked: boolean; /** * Returns `true` if the {@link https://source.android.com/docs/security/features/keystore/attestation#verifiedbootstate-values | boot * state} is `Verified`. Compromised devices (such as some root devices) do not have a valid * boot state. */ abstract isVerifiedBootStateValid: boolean; /** * The result of the certificate chain validation. * * In devices supporting full basic attestation ({@link OnlyDefaultMode}, {@link StrictMode} or * {@link StrictStrongBoxMode}), when a new key is created the device must generate an associated * certificate chain (or certification path) that fulfills the following criteria: * <ul> * <li>The root certificate is a known {@link https://developer.android.com/privacy-and-security/security-key-attestation#root_certificate | Google * root certificate}.</li> * <li>The certificate chain is valid: it does not contain a certificate in the CRL, no certificate * is expired, the certificates in the chain are signed with the previous one, etc.</li> * </ul> * So, when a device supports full basic, returns {@link CertificateChainValidationResult.Success}. */ abstract certificateChainValidationResult: CertificateChainValidationResult; /** * Alternate constructor that creates a {@link FidoUafAttestationInformation} from a json. * * @param json contains the source for instance creation. * @returns a {@link FidoUafAttestationInformation} instance. */ static fromJson(json: any): FidoUafAttestationInformation { const subtype = FidoUafAttestationInformationType[ json.type as keyof typeof FidoUafAttestationInformationType ]; switch (subtype) { case FidoUafAttestationInformationType.OnlySurrogateBasicSupported: return OnlySurrogateBasicSupported.fromJson(json.data); case FidoUafAttestationInformationType.OnlyDefaultMode: return OnlyDefaultMode.fromJson(json.data); case FidoUafAttestationInformationType.StrictMode: return StrictMode.fromJson(json.data); case FidoUafAttestationInformationType.StrictStrongBoxMode: return StrictStrongBoxMode.fromJson(json.data); default: throw new Error(`Unknown FIDO UAF attestation information (${json.type}).`); } } } /** * Only the surrogate basic attestation is supported. * * So, neither the `default`, the `strict` nor the `strict-strongbox` modes of full basic attestation * are supported (see the {@link https://docs.nevis.net/configurationguide/patterns-reference#basic-full-attestation | nevisFIDO documentation} * for details regarding the different modes). * * Supporting only surrogate basic attestation implies that the certificate chain of the device could * not be successfully validated (see {@link certificateChainValidationResult}). This occurs typically * in old devices, and devices that do not contain a Google root certificate (like some Huawei models). */ export abstract class OnlySurrogateBasicSupported extends FidoUafAttestationInformation { /** * The error that occurred while checking if the full basic attestation is supported. * * Its message provides information about why the device does not support full basic attestation. */ abstract cause?: string; /** * Alternate constructor that creates an {@link OnlySurrogateBasicSupported} from a json. * * @param json contains the source for instance creation. * @returns the created {@link OnlySurrogateBasicSupported} instance. */ static fromJson(json: any): OnlySurrogateBasicSupported { return OnlySurrogateBasicSupportedImpl.fromJson(json); } } export class OnlySurrogateBasicSupportedImpl extends OnlySurrogateBasicSupported { keymasterSecurityLevel: SecurityLevel; keymasterVersion: number; isDeviceBootloaderLocked: boolean; isVerifiedBootStateValid: boolean; certificateChainValidationResult: CertificateChainValidationResult; cause: string | undefined; constructor( keymasterSecurityLevel: SecurityLevel, keymasterVersion: number, isDeviceBootloaderLocked: boolean, isVerifiedBootStateValid: boolean, certificateChainValidationResult: CertificateChainValidationResult, cause: string | undefined ) { super(); this.keymasterSecurityLevel = keymasterSecurityLevel; this.keymasterVersion = keymasterVersion; this.isDeviceBootloaderLocked = isDeviceBootloaderLocked; this.isVerifiedBootStateValid = isVerifiedBootStateValid; this.certificateChainValidationResult = certificateChainValidationResult; this.cause = cause; } static fromJson(json: any): OnlySurrogateBasicSupportedImpl { return new OnlySurrogateBasicSupportedImpl( json.keymasterSecurityLevel, json.keymasterVersion, json.isDeviceBootloaderLocked, json.isVerifiedBootStateValid, json.certificateChainValidationResult, json.cause ); } } /** * The device supports the `default` full basic attestation mode as described in the {@link https://docs.nevis.net/configurationguide/patterns-reference#basic-full-attestation | nevisFIDO documentation}. * * It supports surrogate basic attestation, but it does not support neither the `strict` nor the * `strict-strongbox` modes. * * This means that the certificate chain was successfully validated, and thus {@link certificateChainValidationResult} * returns {@link CertificateChainValidationResult.Success}. The device contains hardware using a known * Google root certificate, but does not fulfill at least one of the other criteria required to be * compatible with {@link StrictMode} or {@link StrictStrongBoxMode}. */ export abstract class OnlyDefaultMode extends FidoUafAttestationInformation { /** * The error that occurred while checking if the strict mode of the full basic attestation is * supported. * * Its message provides information about why the device does not support the full basic attestation * strict mode. */ abstract cause?: string; /** * Alternate constructor that creates an {@link OnlyDefaultMode} from a json. * * @param json contains the source for instance creation. * @returns the created {@link OnlyDefaultMode} instance. */ static fromJson(json: any): OnlyDefaultMode { return OnlyDefaultModeImpl.fromJson(json); } } export class OnlyDefaultModeImpl extends OnlyDefaultMode { keymasterSecurityLevel: SecurityLevel; keymasterVersion: number; isDeviceBootloaderLocked: boolean; isVerifiedBootStateValid: boolean; certificateChainValidationResult: CertificateChainValidationResult; cause: string | undefined; constructor( keymasterSecurityLevel: SecurityLevel, keymasterVersion: number, isDeviceBootloaderLocked: boolean, isVerifiedBootStateValid: boolean, certificateChainValidationResult: CertificateChainValidationResult, cause: string | undefined ) { super(); this.keymasterSecurityLevel = keymasterSecurityLevel; this.keymasterVersion = keymasterVersion; this.isDeviceBootloaderLocked = isDeviceBootloaderLocked; this.isVerifiedBootStateValid = isVerifiedBootStateValid; this.certificateChainValidationResult = certificateChainValidationResult; this.cause = cause; } static fromJson(json: any): OnlyDefaultModeImpl { return new OnlyDefaultModeImpl( json.keymasterSecurityLevel, json.keymasterVersion, json.isDeviceBootloaderLocked, json.isVerifiedBootStateValid, json.certificateChainValidationResult, json.cause ); } } /** * The device supports the `default` and `strict` full basic attestation modes as described in the * {@link https://docs.nevis.net/configurationguide/component-installation-guides/nevisFido/fido-uaf-configuration#full-basic-attestation | nevisFIDO documentation}. * It also supports surrogate basic. * * However, since it does not have a StrongBox that the SDK can use to store the FIDO UAF credentials, * the `strict-strongbox` mode is not supported. * * If the device supports this mode, then: * - The FIDO UAF keys will be stored in a Trusted Execution Environment (TEE), and thus {@link keymasterSecurityLevel} * will be {@link SecurityLevel.TrustedEnvironment}. * - The certificate chain was successfully validated, and thus {@link certificateChainValidationResult} * returns {@link CertificateChainValidationResult.Success}. * - The value of {@link keymasterVersion} is 2 or higher. * - The verified boot state is valid ({@link isVerifiedBootStateValid} returns `true`). * - The device bootloader is locked ({@link isDeviceBootloaderLocked} returns `true`). */ export abstract class StrictMode extends FidoUafAttestationInformation { /** * Alternate constructor that creates a {@link StrictMode} from a json. * * @param json contains the source for instance creation. * @returns the created {@link StrictMode} instance. */ static fromJson(json: any): StrictMode { return StrictModeImpl.fromJson(json); } } export class StrictModeImpl extends StrictMode { keymasterSecurityLevel: SecurityLevel; keymasterVersion: number; isDeviceBootloaderLocked: boolean; isVerifiedBootStateValid: boolean; certificateChainValidationResult: CertificateChainValidationResult; constructor( keymasterSecurityLevel: SecurityLevel, keymasterVersion: number, isDeviceBootloaderLocked: boolean, isVerifiedBootStateValid: boolean, certificateChainValidationResult: CertificateChainValidationResult ) { super(); this.keymasterSecurityLevel = keymasterSecurityLevel; this.keymasterVersion = keymasterVersion; this.isDeviceBootloaderLocked = isDeviceBootloaderLocked; this.isVerifiedBootStateValid = isVerifiedBootStateValid; this.certificateChainValidationResult = certificateChainValidationResult; } static fromJson(json: any): StrictModeImpl { return new StrictModeImpl( json.keymasterSecurityLevel, json.keymasterVersion, json.isDeviceBootloaderLocked, json.isVerifiedBootStateValid, json.certificateChainValidationResult ); } } /** * The device supports the `default`, `strict` and `strict-strongbox` full basic attestation modes as * described in the {@link https://docs.nevis.net/configurationguide/component-installation-guides/nevisFido/fido-uaf-configuration#full-basic-attestation | nevisFIDO documentation}. * It also supports surrogate basic. * * If the device supports this mode, then: * - The FIDO UAF keys will be stored in the StrongBox, and thus {@link keymasterSecurityLevel} will * be {@link SecurityLevel.StrongBox}. * - The certificate chain was successfully validated, and thus {@link certificateChainValidationResult} * returns {@link CertificateChainValidationResult.Success}. * - The value of {@link keymasterVersion} is 2 or higher. * - The verified boot state is valid ({@link isVerifiedBootStateValid} returns `true`). * - The device bootloader is locked ({@link isDeviceBootloaderLocked} returns `true`). */ export abstract class StrictStrongBoxMode extends FidoUafAttestationInformation { /** * Alternate constructor that creates a {@link StrictStrongBoxMode} from a json. * * @param json contains the source for instance creation. * @returns the created {@link StrictStrongBoxMode} instance. */ static fromJson(json: any): StrictStrongBoxMode { return StrictStrongBoxModeImpl.fromJson(json); } } export class StrictStrongBoxModeImpl extends StrictStrongBoxMode { keymasterSecurityLevel: SecurityLevel; keymasterVersion: number; isDeviceBootloaderLocked: boolean; isVerifiedBootStateValid: boolean; certificateChainValidationResult: CertificateChainValidationResult; constructor( keymasterSecurityLevel: SecurityLevel, keymasterVersion: number, isDeviceBootloaderLocked: boolean, isVerifiedBootStateValid: boolean, certificateChainValidationResult: CertificateChainValidationResult ) { super(); this.keymasterSecurityLevel = keymasterSecurityLevel; this.keymasterVersion = keymasterVersion; this.isDeviceBootloaderLocked = isDeviceBootloaderLocked; this.isVerifiedBootStateValid = isVerifiedBootStateValid; this.certificateChainValidationResult = certificateChainValidationResult; } static fromJson(json: any): StrictStrongBoxModeImpl { return new StrictStrongBoxModeImpl( json.keymasterSecurityLevel, json.keymasterVersion, json.isDeviceBootloaderLocked, json.isVerifiedBootStateValid, json.certificateChainValidationResult ); } }