diff --git a/CHANGELOG.md b/CHANGELOG.md index 699738f..0896b7c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -82,6 +82,11 @@ out the attestation record. #### 1.2.1 - make all config classes `data` classes -- -#### 1.3.0 -- make configuration play nicely with file-based config loading (e.g. [HopLite](https://github.com/sksamuel/hoplite)) \ No newline at end of file + +### 1.3.0 +- make configuration play nicely with file-based config loading (e.g. [HopLite](https://github.com/sksamuel/hoplite)) + +### 1.4.0 +- reorganized constructors for less confusing file-based config loading +- update to latest conventions plugin +- build against JDK11 as per gradle.properties \ No newline at end of file diff --git a/android-attestation/build.gradle.kts b/android-attestation/build.gradle.kts index 20f33e3..d9579cb 100644 --- a/android-attestation/build.gradle.kts +++ b/android-attestation/build.gradle.kts @@ -3,7 +3,7 @@ import at.asitplus.gradle.ktor import org.gradle.kotlin.dsl.support.listFilesOrdered group = "at.asitplus" -version = "1.3.0" +version = "1.4.0" plugins { kotlin("jvm") diff --git a/android-attestation/src/main/kotlin/AndroidAttestationConfiguration.kt b/android-attestation/src/main/kotlin/AndroidAttestationConfiguration.kt index e1a7126..3b025be 100644 --- a/android-attestation/src/main/kotlin/AndroidAttestationConfiguration.kt +++ b/android-attestation/src/main/kotlin/AndroidAttestationConfiguration.kt @@ -1,7 +1,5 @@ package at.asitplus.attestation.android -import at.asitplus.attestation.android.SoftwareAttestationChecker.Companion.GOOGLE_SOFTWARE_EC_ROOT -import at.asitplus.attestation.android.SoftwareAttestationChecker.Companion.GOOGLE_SOFTWARE_RSA_ROOT import at.asitplus.attestation.android.exceptions.AndroidAttestationException import com.google.android.attestation.Constants.GOOGLE_ROOT_CA_PUB_KEY import io.ktor.util.* @@ -60,12 +58,10 @@ val DEFAULT_SOFTWARE_TRUST_ANCHORS = arrayOf( * @param requireRollbackResistance optional parameter. Unsupported by most devices. * See [Official Documentation](https://source.android.com/docs/security/features/keystore/implementer-ref#rollback_resistance) * @param ignoreLeafValidity optional parameter. Whether to ignore the timely validity of the leaf certificate (looking at you, Samsung!) - * @param hardwareAttestationRootKeys Manually specify the trust anchor for HW-attested certificate chains as X.509-encoded public keys. - * The reason for this format in the default constructor is to make file-based configuration through [Hoplite](https://github.com/sksamuel/hoplite) a breeze. + * @param hardwareAttestationTrustAnchors Manually specify the trust anchor for HW-attested certificate chains. * Defaults to google HW attestation key. Overriding this set is useful for automated end-to-end tests, for example. * The default trust anchors are accessible through [DEFAULT_HARDWARE_TRUST_ANCHORS] - * @param hardwareAttestationRootKeys Manually specify the trust anchor for SW-attested certificate chains as X.509-encoded public keys. - * The reason for this format in the default constructor is to make file-based configuration through [Hoplite](https://github.com/sksamuel/hoplite) a breeze. + * @param softwareAttestationTrustAnchors Manually specify the trust anchor for SW-attested certificate chains. * Defaults to google SW attestation keys. Overriding this set is useful for automated end-to-end tests, for example. * The default trust anchors are accessible through [DEFAULT_SOFTWARE_TRUST_ANCHORS] * @param disableHardwareAttestation Entirely disable creation of a [HardwareAttestationChecker]. @@ -81,7 +77,12 @@ val DEFAULT_SOFTWARE_TRUST_ANCHORS = arrayOf( * Enabling this flag, while keeping [disableHardwareAttestation] `true` makes is possible to instantiate both a * [HardwareAttestationChecker] and a [SoftwareAttestationChecker]. */ -data class AndroidAttestationConfiguration( +data class AndroidAttestationConfiguration @JvmOverloads constructor( + + /** + * List of applications, which can be attested + */ + val applications: List, /** * optional parameter. If set, attestation enforces Android version to be greater or equal to this parameter. @@ -120,25 +121,18 @@ data class AndroidAttestationConfiguration( val ignoreLeafValidity: Boolean = false, /** - * Manually specify the trust anchors for HW-attested certificate chains as X.509-encoded public keys. - * The reason for this format in the default constructor is to make file-based configuration through [Hoplite](https://github.com/sksamuel/hoplite) a breeze. - * Defaults to google HW attestation key. + * Manually specify the trust anchor for HW-attested certificate chains. Defaults to google HW attestation key. * Overriding this set is useful for automated end-to-end tests, for example. - * The default trust anchor is accessible through [GOOGLE_ROOT_CA_PUB_KEY]. + * The default trust anchors are accessible through [DEFAULT_HARDWARE_TRUST_ANCHORS] */ - private val hardwareAttestationRootKeys: Set = linkedSetOf(GOOGLE_ROOT_CA_PUB_KEY.decodeBase64Bytes()), + val hardwareAttestationTrustAnchors: Set = linkedSetOf(*DEFAULT_HARDWARE_TRUST_ANCHORS), /** - * Manually specify the trust anchor for SW-attested certificate chains as X.509-encoded public keys. - * The reason for this format in the default constructor is to make file-based configuration through [Hoplite](https://github.com/sksamuel/hoplite) a breeze. - * Defaults to google SW attestation keys. + * Manually specify the trust anchor for SW-attested certificate chains. Defaults to google SW attestation keys. * Overriding this set is useful for automated end-to-end tests, for example. - * The default trust anchors are [GOOGLE_SOFTWARE_EC_ROOT], [GOOGLE_SOFTWARE_RSA_ROOT] + * The default trust anchors are accessible through [DEFAULT_SOFTWARE_TRUST_ANCHORS] */ - private val softwareAttestationRootKeys: Set = linkedSetOf( - GOOGLE_SOFTWARE_EC_ROOT.decodeBase64Bytes(), - GOOGLE_SOFTWARE_RSA_ROOT.decodeBase64Bytes() - ), + val softwareAttestationTrustAnchors: Set = linkedSetOf(*DEFAULT_SOFTWARE_TRUST_ANCHORS), /** * Tolerance in seconds added to verification date @@ -168,21 +162,16 @@ data class AndroidAttestationConfiguration( */ val enableSoftwareAttestation: Boolean = false, - /** - * List of applications, which can be attested - */ - val applications: List, - ) { /** - * Convenience constructor to attest a single app + * Convenience constructor to attest a single app1 */ constructor( /** - * List of applications, which can be attested + * The single application to be attested */ - applications: List, + singleApp: AppData, /** * optional parameter. If set, attestation enforces Android version to be greater or equal to this parameter. @@ -239,7 +228,6 @@ data class AndroidAttestationConfiguration( */ verificationSecondsOffset: Int = 0, - /** * Entirely disable creation of a [HardwareAttestationChecker]. Only change this flag, if you **really** know what * you are doing! @@ -255,7 +243,6 @@ data class AndroidAttestationConfiguration( */ enableNougatAttestation: Boolean = false, - /** * Enables software attestation. A [SoftwareAttestationChecker] can only be instantiated if this flag is set to true. * Only change this flag, if you **really** know what you are doing! @@ -264,15 +251,15 @@ data class AndroidAttestationConfiguration( */ enableSoftwareAttestation: Boolean = false ) : this( - applications = applications, + listOf(singleApp), androidVersion = androidVersion, patchLevel = patchLevel, requireStrongBox = requireStrongBox, allowBootloaderUnlock = allowBootloaderUnlock, requireRollbackResistance = requireRollbackResistance, ignoreLeafValidity = ignoreLeafValidity, - hardwareAttestationRootKeys = hardwareAttestationTrustAnchors.map { it.encoded }.toSet(), - softwareAttestationRootKeys = softwareAttestationTrustAnchors.map { it.encoded }.toSet(), + hardwareAttestationTrustAnchors = hardwareAttestationTrustAnchors, + softwareAttestationTrustAnchors = softwareAttestationTrustAnchors, verificationSecondsOffset = verificationSecondsOffset, disableHardwareAttestation = disableHardwareAttestation, enableNougatAttestation = enableNougatAttestation, @@ -280,20 +267,15 @@ data class AndroidAttestationConfiguration( ) /** - * Convenience constructor to attest a single app + * Constructor used when loading this class from a config file through [Hoplite](https://github.com/sksamuel/hoplite) */ constructor( - /** - * A single application to configure - */ - singleApp: AppData, - /** * optional parameter. If set, attestation enforces Android version to be greater or equal to this parameter. * **Caution:** Major Android versions increment in steps of thousands. I.e. Android 11 is specified as `11000` * Can be overridden for individual apps */ - androidVersion: Int? = null, + version: Int? = null, /** * optional parameter. If set, attestation enforces Security patch level to be greater or equal to this parameter. @@ -324,31 +306,18 @@ data class AndroidAttestationConfiguration( */ ignoreLeafValidity: Boolean = false, - /** - * Manually specify the trust anchor for HW-attested certificate chains. Defaults to google HW attestation key. - * Overriding this set is useful for automated end-to-end tests, for example. - * The default trust anchors are accessible through [DEFAULT_HARDWARE_TRUST_ANCHORS] - */ - hardwareAttestationTrustAnchors: Set = linkedSetOf(*DEFAULT_HARDWARE_TRUST_ANCHORS), - - /** - * Manually specify the trust anchor for SW-attested certificate chains. Defaults to google SW attestation keys. - * Overriding this set is useful for automated end-to-end tests, for example. - * The default trust anchors are accessible through [DEFAULT_SOFTWARE_TRUST_ANCHORS] - */ - softwareAttestationTrustAnchors: Set = linkedSetOf(*DEFAULT_SOFTWARE_TRUST_ANCHORS), /** * Tolerance in seconds added to verification date */ verificationSecondsOffset: Int = 0, - /** * Entirely disable creation of a [HardwareAttestationChecker]. Only change this flag, if you **really** know what * you are doing! * @see enableSoftwareAttestation */ + disableHardwareAttestation: Boolean = false, /** @@ -359,34 +328,53 @@ data class AndroidAttestationConfiguration( */ enableNougatAttestation: Boolean = false, - /** * Enables software attestation. A [SoftwareAttestationChecker] can only be instantiated if this flag is set to true. * Only change this flag, if you **really** know what you are doing! * Enabling this flag, while keeping [disableHardwareAttestation] `true` makes is possible to instantiate both a * [HardwareAttestationChecker] and a [SoftwareAttestationChecker]. */ - enableSoftwareAttestation: Boolean = false + enableSoftwareAttestation: Boolean = false, + + + /** + * Manually specify the trust anchors for HW-attested certificate chains as X.509-encoded public keys. + * The reason for this format in the default constructor is to make file-based configuration through [Hoplite](https://github.com/sksamuel/hoplite) a breeze. + * Defaults to google HW attestation key. + * Overriding this set is useful for automated end-to-end tests, for example. + * The default trust anchor is accessible through [GOOGLE_ROOT_CA_PUB_KEY]. + */ + hardwareAttestationRootKeys: Set = DEFAULT_HARDWARE_TRUST_ANCHORS.map { it.encoded }.toSet(), + + /** + * Manually specify the trust anchor for SW-attested certificate chains as X.509-encoded public keys. + * The reason for this format in the default constructor is to make file-based configuration through [Hoplite](https://github.com/sksamuel/hoplite) a breeze. + * Defaults to google SW attestation keys. + * Overriding this set is useful for automated end-to-end tests, for example. + * The default trust anchors are [GOOGLE_SOFTWARE_EC_ROOT], [GOOGLE_SOFTWARE_RSA_ROOT] + */ + softwareAttestationRootKeys: Set = DEFAULT_SOFTWARE_TRUST_ANCHORS.map { it.encoded }.toSet(), + + /** + * List of applications, which can be attested + */ + apps: List, ) : this( - listOf(singleApp), - androidVersion = androidVersion, + applications = apps, + androidVersion = version, patchLevel = patchLevel, requireStrongBox = requireStrongBox, allowBootloaderUnlock = allowBootloaderUnlock, requireRollbackResistance = requireRollbackResistance, ignoreLeafValidity = ignoreLeafValidity, - hardwareAttestationTrustAnchors = hardwareAttestationTrustAnchors, - softwareAttestationTrustAnchors = softwareAttestationTrustAnchors, + hardwareAttestationTrustAnchors = hardwareAttestationRootKeys.map { it.parsePublicKey() }.toSet(), + softwareAttestationTrustAnchors = softwareAttestationRootKeys.map { it.parsePublicKey() }.toSet(), verificationSecondsOffset = verificationSecondsOffset, disableHardwareAttestation = disableHardwareAttestation, enableNougatAttestation = enableNougatAttestation, enableSoftwareAttestation = enableSoftwareAttestation ) - val hardwareAttestationTrustAnchors: Set = - hardwareAttestationRootKeys.map { it.parsePublicKey() }.toSet() - val softwareAttestationTrustAnchors = softwareAttestationRootKeys.map { it.parsePublicKey() }.toSet() - /** * Internal representation of the patch level as contained in the [com.google.android.attestation.ParsedAttestationRecord] */ @@ -565,7 +553,7 @@ data class AndroidAttestationConfiguration( * adds a single hardware attestation trust anchor * @see AndroidAttestationConfiguration.hardwareAttestationTrustAnchors */ - fun addHardwareAttestationTurstAnchor(anchor: PublicKey) = apply { hardwareAttestationTrustAnchors += anchor } + fun addHardwareAttestationTrustAnchor(anchor: PublicKey) = apply { hardwareAttestationTrustAnchors += anchor } /** * @see AndroidAttestationConfiguration.softwareAttestationTrustAnchors @@ -607,8 +595,8 @@ data class AndroidAttestationConfiguration( allowBootloaderUnlock = bootloaderUnlockAllowed, requireRollbackResistance = rollbackResitanceRequired, ignoreLeafValidity = ignoreLeafValidity, - hardwareAttestationRootKeys = hardwareAttestationTrustAnchors.map { it.encoded }.toSet(), - softwareAttestationRootKeys = softwareAttestationTrustAnchors.map { it.encoded }.toSet(), + hardwareAttestationTrustAnchors = hardwareAttestationTrustAnchors, + softwareAttestationTrustAnchors = softwareAttestationTrustAnchors, verificationSecondsOffset = verificationSecondsOffset, disableHardwareAttestation = disableHwAttestation, enableSoftwareAttestation = enableSwAttestation, @@ -627,5 +615,4 @@ private fun ByteArray.parsePublicKey() = }.getOrElse { throw object : AndroidAttestationException("Not a valid public key: ${this.encodeBase64()}", null) {} } - } - + } \ No newline at end of file diff --git a/android-attestation/src/test/kotlin/FakeAttestationTests.kt b/android-attestation/src/test/kotlin/FakeAttestationTests.kt index 187b73e..27b6371 100644 --- a/android-attestation/src/test/kotlin/FakeAttestationTests.kt +++ b/android-attestation/src/test/kotlin/FakeAttestationTests.kt @@ -123,7 +123,7 @@ class FakeAttestationTests : FreeSpec({ "and the fake attestation must not verify against the google root key" { val trustedChecker = HardwareAttestationChecker( AndroidAttestationConfiguration( - listOf( + applications = listOf( AndroidAttestationConfiguration.AppData( packageName = packageName, signatureDigests = listOf(signatureDigest), diff --git a/attestation-diag/src/main/kotlin/Diag.kt b/attestation-diag/src/main/kotlin/Diag.kt index 36459f6..ba95441 100644 --- a/attestation-diag/src/main/kotlin/Diag.kt +++ b/attestation-diag/src/main/kotlin/Diag.kt @@ -13,7 +13,7 @@ import com.google.gson.JsonSerializer fun main(args: Array) { if (args.isEmpty()) { - System.err.println("Certificat neither specified in a file (-f ) nor as parameter !") + System.err.println("Certificate neither specified in a file (-f ) nor as parameter !") System.exit(1) } val certB64 = if (args[0] == "-f") java.io.File(args[1]).readText() else args[0] diff --git a/build.gradle.kts b/build.gradle.kts index d3434c8..d7cb6ce 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,3 +1,3 @@ -plugins { id("at.asitplus.gradle.conventions") version "1.9.10+20230911" } +plugins { id("at.asitplus.gradle.conventions") version "1.9.10+20230922" } group = "at.asitplus" \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index e69de29..7b69c84 100644 --- a/gradle.properties +++ b/gradle.properties @@ -0,0 +1 @@ +jvm.version=11 \ No newline at end of file