Skip to content

Commit

Permalink
- skipp validation if base45 decoding failed; (eu-digital-green-certi…
Browse files Browse the repository at this point in the history
  • Loading branch information
MykhailoNester authored Nov 2, 2021
1 parent c751fd6 commit 24a36ab
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 89 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ class VerificationFragment : DialogFragment() {
DEBUG_DATA to qrCodeVerificationResult.debugData
)
)
} else {
dismiss()
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,18 +65,18 @@ import javax.inject.Inject

@HiltViewModel
class VerificationViewModel @Inject constructor(
private val prefixValidationService: PrefixValidationService,
private val base45Service: Base45Service,
private val compressorService: CompressorService,
private val cryptoService: CryptoService,
private val coseService: CoseService,
private val schemaValidator: SchemaValidator,
private val cborService: CborService,
private val verifierRepository: VerifierRepository,
private val engine: CertLogicEngine,
private val getRulesUseCase: GetRulesUseCase,
private val valueSetsRepository: ValueSetsRepository,
private val preferences: Preferences
private val prefixValidationService: PrefixValidationService,
private val base45Service: Base45Service,
private val compressorService: CompressorService,
private val cryptoService: CryptoService,
private val coseService: CoseService,
private val schemaValidator: SchemaValidator,
private val cborService: CborService,
private val verifierRepository: VerifierRepository,
private val engine: CertLogicEngine,
private val getRulesUseCase: GetRulesUseCase,
private val valueSetsRepository: ValueSetsRepository,
private val preferences: Preferences
) : ViewModel() {

private val _qrCodeVerificationResult = MutableLiveData<QrCodeVerificationResult>()
Expand All @@ -93,42 +93,42 @@ class VerificationViewModel @Inject constructor(
val innerVerificationResult: InnerVerificationResult = validateCertificate(code, verificationResult)

val validationResults: List<ValidationResult>? =
if (verificationResult.isValid() && innerVerificationResult.base64EncodedKid?.isNotBlank() == true) {
innerVerificationResult.greenCertificateData?.validateRules(
verificationResult,
innerVerificationResult.certificateIssuingCountryIsoCode.orEmpty(),
countryOfArrivalIsoCode,
innerVerificationResult.base64EncodedKid
)
} else {
null
}
if (verificationResult.isValid() && innerVerificationResult.base64EncodedKid?.isNotBlank() == true) {
innerVerificationResult.greenCertificateData?.validateRules(
verificationResult,
innerVerificationResult.certificateIssuingCountryIsoCode.orEmpty(),
countryOfArrivalIsoCode,
innerVerificationResult.base64EncodedKid
)
} else {
null
}

if (innerVerificationResult.isApplicableCode) {
val covidCertificate = innerVerificationResult.greenCertificateData?.greenCertificate
val certificateModel = covidCertificate?.toCertificateModel()
val hcert: String? = innerVerificationResult.greenCertificateData?.hcertJson
val standardizedVerificationResult: StandardizedVerificationResult =
extractStandardizedVerificationResultFrom(
verificationResult,
innerVerificationResult
)
extractStandardizedVerificationResultFrom(
verificationResult,
innerVerificationResult
)

val isDebugModeEnabled =
standardizedVerificationResult.category != StandardizedVerificationResultCategory.VALID
&& (preferences.debugModeState?.let { DebugModeState.valueOf(it) }
?: DebugModeState.OFF) != DebugModeState.OFF
&& preferences.debugModeSelectedCountriesCodes?.contains(
innerVerificationResult.greenCertificateData?.getNormalizedIssuingCountry()
) == true
standardizedVerificationResult.category != StandardizedVerificationResultCategory.VALID
&& (preferences.debugModeState?.let { DebugModeState.valueOf(it) }
?: DebugModeState.OFF) != DebugModeState.OFF
&& preferences.debugModeSelectedCountriesCodes?.contains(
innerVerificationResult.greenCertificateData?.getNormalizedIssuingCountry()
) == true

QrCodeVerificationResult.Applicable(
standardizedVerificationResult,
certificateModel,
hcert,
validationResults?.toRuleValidationResultModels(),
isDebugModeEnabled,
innerVerificationResult.debugData
standardizedVerificationResult,
certificateModel,
hcert,
validationResults?.toRuleValidationResultModels(),
isDebugModeEnabled,
innerVerificationResult.debugData
)
} else {
QrCodeVerificationResult.NotApplicable
Expand All @@ -140,39 +140,46 @@ class VerificationViewModel @Inject constructor(
}

private suspend fun validateCertificate(
code: String,
verificationResult: VerificationResult
code: String,
verificationResult: VerificationResult
): InnerVerificationResult {
var greenCertificateData: GreenCertificateData? = null
var isApplicableCode = false

val plainInput = prefixValidationService.decode(code, verificationResult)
val compressedCose = base45Service.decode(plainInput, verificationResult)
val cose: ByteArray? = compressorService.decode(compressedCose, verificationResult)
if (verificationResult.base45Decoded.not()) {
Timber.d("Verification failed: base45 not decoded")
return InnerVerificationResult(
greenCertificateData = greenCertificateData,
isApplicableCode = isApplicableCode
)
}

val cose: ByteArray? = compressorService.decode(compressedCose, verificationResult)
if (cose == null) {
Timber.d("Verification failed: Too many bytes read")
return InnerVerificationResult(
greenCertificateData = greenCertificateData,
isApplicableCode = isApplicableCode
greenCertificateData = greenCertificateData,
isApplicableCode = isApplicableCode
)
}

val coseData = coseService.decode(cose, verificationResult)
if (coseData == null) {
Timber.d("Verification failed: COSE not decoded")
return InnerVerificationResult(
greenCertificateData = greenCertificateData,
isApplicableCode = isApplicableCode
greenCertificateData = greenCertificateData,
isApplicableCode = isApplicableCode
)
}

val kid = coseData.kid
if (kid == null) {
Timber.d("Verification failed: cannot extract kid from COSE")
return InnerVerificationResult(
greenCertificateData = greenCertificateData,
isApplicableCode = isApplicableCode
greenCertificateData = greenCertificateData,
isApplicableCode = isApplicableCode
)
}

Expand All @@ -187,21 +194,21 @@ class VerificationViewModel @Inject constructor(
if (certificates.isEmpty()) {
Timber.d("Verification failed: failed to load certificate")
return InnerVerificationResult(
greenCertificateData = greenCertificateData,
isApplicableCode = isApplicableCode,
base64EncodedKid = base64EncodedKid
greenCertificateData = greenCertificateData,
isApplicableCode = isApplicableCode,
base64EncodedKid = base64EncodedKid
)
}
val noPublicKeysFound = false
var certificateExpired = false
var issuingCountry = ""
certificates.forEach { innerCertificate ->
cryptoService.validate(
cose,
innerCertificate,
verificationResult,
greenCertificateData?.greenCertificate?.getType()
?: dgca.verifier.app.decoder.model.CertificateType.UNKNOWN
cose,
innerCertificate,
verificationResult,
greenCertificateData?.greenCertificate?.getType()
?: dgca.verifier.app.decoder.model.CertificateType.UNKNOWN
)

if (verificationResult.coseVerified) {
Expand All @@ -222,21 +229,22 @@ class VerificationViewModel @Inject constructor(
}

return InnerVerificationResult(
noPublicKeysFound = noPublicKeysFound,
certificateExpired = certificateExpired,
certificateIssuingCountryIsoCode = issuingCountry,
greenCertificateData = greenCertificateData,
isApplicableCode = isApplicableCode,
base64EncodedKid = base64EncodedKid,
debugData = DebugData(code, cose, coseData.cbor)
noPublicKeysFound = noPublicKeysFound,
certificateExpired = certificateExpired,
certificateIssuingCountryIsoCode = issuingCountry,
greenCertificateData = greenCertificateData,
isApplicableCode = isApplicableCode,
base64EncodedKid = base64EncodedKid,
debugData = DebugData(code, cose, coseData.cbor)
)
}


private suspend fun GreenCertificateData.validateRules(
verificationResult: VerificationResult,
certificateIssuingCountryIsoCode: String,
countryOfArrivalIsoCode: String,
base64EncodedKid: String
verificationResult: VerificationResult,
certificateIssuingCountryIsoCode: String,
countryOfArrivalIsoCode: String,
base64EncodedKid: String
): List<ValidationResult>? {
this.apply {
val engineCertificateType = this.greenCertificate.getEngineCertificateType()
Expand All @@ -248,10 +256,10 @@ class VerificationViewModel @Inject constructor(
this.getNormalizedIssuingCountry()
}
val rules = getRulesUseCase.invoke(
ZonedDateTime.now().withZoneSameInstant(UTC_ZONE_ID),
countryOfArrivalIsoCode,
issuingCountry,
engineCertificateType
ZonedDateTime.now().withZoneSameInstant(UTC_ZONE_ID),
countryOfArrivalIsoCode,
issuingCountry,
engineCertificateType
)
val valueSetsMap = mutableMapOf<String, List<String>>()
valueSetsRepository.getValueSets().forEach { valueSet ->
Expand All @@ -263,21 +271,21 @@ class VerificationViewModel @Inject constructor(
}

val externalParameter = ExternalParameter(
validationClock = ZonedDateTime.now(ZoneId.of(ZoneOffset.UTC.id)),
valueSets = valueSetsMap,
countryCode = countryOfArrivalIsoCode,
exp = this.expirationTime,
iat = this.issuedAt,
issuerCountryCode = issuingCountry,
kid = base64EncodedKid,
region = "",
validationClock = ZonedDateTime.now(ZoneId.of(ZoneOffset.UTC.id)),
valueSets = valueSetsMap,
countryCode = countryOfArrivalIsoCode,
exp = this.expirationTime,
iat = this.issuedAt,
issuerCountryCode = issuingCountry,
kid = base64EncodedKid,
region = "",
)
val validationResults = engine.validate(
engineCertificateType,
this.greenCertificate.schemaVersion,
rules,
externalParameter,
this.hcertJson
engineCertificateType,
this.greenCertificate.schemaVersion,
rules,
externalParameter,
this.hcertJson
)

validationResults.forEach {
Expand Down Expand Up @@ -306,8 +314,8 @@ class VerificationViewModel @Inject constructor(
companion object {

fun validateCertData(
certificate: GreenCertificate?,
verificationResult: VerificationResult
certificate: GreenCertificate?,
verificationResult: VerificationResult
) {
certificate?.vaccinations?.let {
if (it.isNotEmpty()) {
Expand All @@ -326,10 +334,10 @@ class VerificationViewModel @Inject constructor(
if (it.isNotEmpty()) {
val recovery = it.first()
verificationResult.recoveryVerification =
RecoveryVerificationResult(
recovery.isCertificateNotValidSoFar() == true,
recovery.isCertificateNotValidAnymore() == true
)
RecoveryVerificationResult(
recovery.isCertificateNotValidSoFar() == true,
recovery.isCertificateNotValidAnymore() == true
)
}
}
}
Expand Down

0 comments on commit 24a36ab

Please sign in to comment.