diff --git a/gradle.properties b/gradle.properties index 14315a37..91a06546 100644 --- a/gradle.properties +++ b/gradle.properties @@ -43,7 +43,7 @@ systemProp.sonar.gradle.skipCompile=true systemProp.sonar.coverage.jacoco.xmlReportPaths=build/reports/jacoco/testDebugUnitTestCoverage/testDebugUnitTestCoverage.xml,build/reports/jacoco/testReleaseUnitTestCoverage/testReleaseUnitTestCoverage.xml systemProp.sonar.projectName=eudi-lib-android-wallet-core -VERSION_NAME=0.3.2-SNAPSHOT +VERSION_NAME=0.3.3-SNAPSHOT SONATYPE_HOST=S01 SONATYPE_AUTOMATIC_RELEASE=false diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 96a608d4..7462a2a6 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,9 +9,9 @@ dependency-license-report = "2.4" dependencycheck = "8.4.2" espresso-contrib = "3.5.1" espresso-core = "3.5.1" -eudi-document-manager = "0.2.0-SNAPSHOT" +eudi-document-manager = "0.2.1-SNAPSHOT" eudi-iso18013-data-transfer = "0.1.0-SNAPSHOT" -eudi-lib-jvm-openid4vci-kt = "0.1.1-SNAPSHOT" +eudi-lib-jvm-openid4vci-kt = "0.1.2-SNAPSHOT" gradle-plugin = "7.4.0" hamcrestAll = "1.3" identity-credential = "20231002" diff --git a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/EudiWallet.kt b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/EudiWallet.kt index 02a2a2d4..0d471cd0 100644 --- a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/EudiWallet.kt +++ b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/EudiWallet.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 European Commission + * Copyright (c) 2023-2024 European Commission * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -106,6 +106,7 @@ object EudiWallet { .apply { storageDir = config.documentsStorageDir useEncryption = config.encryptDocumentsInStorage + checkPublicKeyBeforeAdding = config.verifyMsoPublicKey } .build() as DocumentManagerImpl diff --git a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/EudiWalletConfig.kt b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/EudiWalletConfig.kt index a4bde74b..aa46e579 100644 --- a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/EudiWalletConfig.kt +++ b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/EudiWalletConfig.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 European Commission + * Copyright (c) 2023-2024 European Commission * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -45,9 +45,9 @@ import java.security.cert.X509Certificate * @property userAuthenticationRequired If true, the user will be asked to authenticate before accessing the documents' attestations. The default value is false. * @property userAuthenticationTimeOut This is the time out for the user authentication. The default value is 30 seconds. * @property trustedReaderCertificates This is the list of trusted reader certificates. If not set, no reader authentication will be performed. + * @property verifyMsoPublicKey If true, the MSO public key will be verified against the public key that is used to issue the document. The default value is true. * @property openId4VpVerifierApiUri This is the uri of the verifier that will be used to verify using OpenId4Vp. If not set OpenId4Vp will not be available. * @property openId4VciConfig This is the config that will be used to issue using OpenId4Vci. If not set OpenId4Vci will not be available. - * @property debugEnabled If true, debug logs will be enabled. The default value is false. * */ @@ -140,6 +140,8 @@ class EudiWalletConfig private constructor(builder: Builder) { val blePeripheralServerModeEnabled: Boolean = bleTransferMode and BLE_SERVER_PERIPHERAL_MODE != 0 + val verifyMsoPublicKey: Boolean = builder.verifyMsoPublicKey + /** * OpenId4Vp verifier uri * This is the uri of the verifier that will be used to verify using OpenId4Vp. @@ -155,9 +157,20 @@ class EudiWalletConfig private constructor(builder: Builder) { /** * Builder * - * @constructor - * + * @constructor Create Builder * @param context + * + * @property documentsStorageDir This is the directory where the documents will be stored. If not set, the default directory is the noBackupFilesDir. + * @property encryptDocumentsInStorage If true, the documents will be encrypted in the storage. The default value is true. + * @property useHardwareToStoreKeys If true and supported by device, documents' keys will be stored in the hardware. The default value is true. + * @property bleTransferMode This is the BLE transfer mode. It can be [BLE_SERVER_PERIPHERAL_MODE], [BLE_CLIENT_CENTRAL_MODE] or both. The default value is [BLE_SERVER_PERIPHERAL_MODE]. + * @property bleClearCacheEnabled If true, the BLE cache will be cleared after each transfer. The default value is false. + * @property userAuthenticationRequired If true, the user will be asked to authenticate before accessing the documents' attestations. The default value is false. + * @property userAuthenticationTimeOut This is the time out for the user authentication. The default value is 30 seconds. + * @property trustedReaderCertificates This is the list of trusted reader certificates. If not set, no reader authentication will be performed. + * @property verifyMsoPublicKey If true, the MSO public key will be verified against the public key that is used to issue the document. The default value is true. + * @property openId4VpVerifierApiUri This is the uri of the verifier that will be used to verify using OpenId4Vp. If not set OpenId4Vp will not be available. + * @property openId4VciConfig This is the config that will be used to issue using OpenId4Vci. If not set OpenId4Vci will not be available. */ class Builder(context: Context) { private val context: Context = context.applicationContext @@ -172,6 +185,7 @@ class EudiWalletConfig private constructor(builder: Builder) { var userAuthenticationRequired: Boolean = false var userAuthenticationTimeOut: Long = 30 * 1000 var trustedReaderCertificates: List? = null + var verifyMsoPublicKey: Boolean = true var openId4VpVerifierApiUri: String? = null var openId4VciConfig: OpenId4VciConfig? = null @@ -285,6 +299,17 @@ class EudiWalletConfig private constructor(builder: Builder) { trustedReaderCertificates(rawIds.map { context.getCertificate(it) }) } + /** + * Verify that the MSO public key is the same as the one used to issue the document. + * If true, the MSO public key will be verified against the public key that is used to issue the document. + * The default value is true. + * + * @param verifyMsoPublicKey + */ + fun verifyMsoPublicKey(verifyMsoPublicKey: Boolean) = apply { + this.verifyMsoPublicKey = verifyMsoPublicKey + } + /** * OpenId4Vp verifier uri * This is the uri of the OpenId4Vp verifier diff --git a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/document/issue/openid4vci/OpenId4VciManager.kt b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/document/issue/openid4vci/OpenId4VciManager.kt index ddbcea12..21a01e73 100644 --- a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/document/issue/openid4vci/OpenId4VciManager.kt +++ b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/document/issue/openid4vci/OpenId4VciManager.kt @@ -24,7 +24,6 @@ import android.util.Log import com.nimbusds.jose.JWSAlgorithm import com.nimbusds.jose.jwk.Curve import eu.europa.ec.eudi.openid4vci.AuthorizationCode -import eu.europa.ec.eudi.openid4vci.AuthorizationServerMetadataResolver import eu.europa.ec.eudi.openid4vci.AuthorizedRequest import eu.europa.ec.eudi.openid4vci.CredentialIdentifier import eu.europa.ec.eudi.openid4vci.CredentialIssuerId @@ -80,7 +79,7 @@ class OpenId4VciManager( get() = OpenId4VCIConfig( clientId = config.clientId, authFlowRedirectionURI = context.openId4VciAuthorizationRedirectUri, - keyGenerationConfig = KeyGenerationConfig(Curve.P_256, 2048) + keyGenerationConfig = KeyGenerationConfig.ecOnly(Curve.P_256) ) private val proofAlgorithm @@ -173,10 +172,7 @@ class OpenId4VciManager( } private suspend fun CredentialIssuerMetadata.getIssuer(): Issuer { - val authorizationServer = authorizationServers.first() - val authMetadata = AuthorizationServerMetadataResolver().resolve(authorizationServer) - .getOrThrow() - return Issuer.make(authMetadata, this, openId4VCIConfig) + return Issuer.make(openId4VCIConfig, credentialIssuerId = credentialIssuerIdentifier) } private suspend fun Issuer.authorize(credentialIdentifier: CredentialIdentifier): AuthorizedRequest {