Skip to content

Commit

Permalink
1.4.0
Browse files Browse the repository at this point in the history
  • Loading branch information
JesusMcCloud committed Oct 18, 2023
1 parent 7458882 commit 796a1f2
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 76 deletions.
11 changes: 8 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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))

### 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
2 changes: 1 addition & 1 deletion android-attestation/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
125 changes: 56 additions & 69 deletions android-attestation/src/main/kotlin/AndroidAttestationConfiguration.kt
Original file line number Diff line number Diff line change
@@ -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.*
Expand Down Expand Up @@ -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].
Expand All @@ -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<AppData>,

/**
* optional parameter. If set, attestation enforces Android version to be greater or equal to this parameter.
Expand Down Expand Up @@ -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<ByteArray> = linkedSetOf(GOOGLE_ROOT_CA_PUB_KEY.decodeBase64Bytes()),
val hardwareAttestationTrustAnchors: Set<PublicKey> = 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<ByteArray> = linkedSetOf(
GOOGLE_SOFTWARE_EC_ROOT.decodeBase64Bytes(),
GOOGLE_SOFTWARE_RSA_ROOT.decodeBase64Bytes()
),
val softwareAttestationTrustAnchors: Set<PublicKey> = linkedSetOf(*DEFAULT_SOFTWARE_TRUST_ANCHORS),

/**
* Tolerance in seconds added to verification date
Expand Down Expand Up @@ -168,21 +162,16 @@ data class AndroidAttestationConfiguration(
*/
val enableSoftwareAttestation: Boolean = false,

/**
* List of applications, which can be attested
*/
val applications: List<AppData>,

) {

/**
* 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<AppData>,
singleApp: AppData,

/**
* optional parameter. If set, attestation enforces Android version to be greater or equal to this parameter.
Expand Down Expand Up @@ -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!
Expand All @@ -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!
Expand All @@ -264,36 +251,31 @@ 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,
enableSoftwareAttestation = enableSoftwareAttestation
)

/**
* 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.
Expand Down Expand Up @@ -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<PublicKey> = 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<PublicKey> = 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,

/**
Expand All @@ -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<ByteArray> = 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<ByteArray> = DEFAULT_SOFTWARE_TRUST_ANCHORS.map { it.encoded }.toSet(),

/**
* List of applications, which can be attested
*/
apps: List<AppData>,
) : 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<PublicKey> =
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]
*/
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand All @@ -627,5 +615,4 @@ private fun ByteArray.parsePublicKey() =
}.getOrElse {
throw object : AndroidAttestationException("Not a valid public key: ${this.encodeBase64()}", null) {}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
2 changes: 1 addition & 1 deletion attestation-diag/src/main/kotlin/Diag.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import com.google.gson.JsonSerializer
fun main(args: Array<String>) {

if (args.isEmpty()) {
System.err.println("Certificat neither specified in a file (-f <path to PEM/Base64 cert>) nor as parameter <Base64 cert>!")
System.err.println("Certificate neither specified in a file (-f <path to PEM/Base64 cert>) nor as parameter <Base64 cert>!")
System.exit(1)
}
val certB64 = if (args[0] == "-f") java.io.File(args[1]).readText() else args[0]
Expand Down
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
@@ -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"
1 change: 1 addition & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
jvm.version=11

0 comments on commit 796a1f2

Please sign in to comment.