diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/TraceLocationVerifier.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/TraceLocationVerifier.kt
new file mode 100644
index 0000000000000000000000000000000000000000..abd313609ebdd09320116af2a9a86fdeafb125c9
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/TraceLocationVerifier.kt
@@ -0,0 +1,76 @@
+package de.rki.coronawarnapp.eventregistration.checkins.qrcode
+
+import androidx.annotation.StringRes
+import dagger.Reusable
+import de.rki.coronawarnapp.R
+import de.rki.coronawarnapp.server.protocols.internal.pt.TraceLocationOuterClass
+import javax.inject.Inject
+
+@Reusable
+class TraceLocationVerifier @Inject constructor() {
+    @Suppress("ReturnCount")
+    fun verifyTraceLocation(protoQrCodePayload: TraceLocationOuterClass.QRCodePayload): VerificationResult {
+        val traceLocation = protoQrCodePayload.traceLocation()
+
+        if (traceLocation.description.isEmpty()) {
+            return VerificationResult.Invalid.Description
+        }
+
+        if (traceLocation.description.length > QR_CODE_DESCRIPTION_MAX_LENGTH) {
+            return VerificationResult.Invalid.Description
+        }
+
+        if (traceLocation.description.lines().size > 1) {
+            return VerificationResult.Invalid.Description
+        }
+
+        if (traceLocation.address.isEmpty()) {
+            return VerificationResult.Invalid.Address
+        }
+
+        if (traceLocation.address.length > QR_CODE_ADDRESS_MAX_LENGTH) {
+            return VerificationResult.Invalid.Address
+        }
+
+        if (traceLocation.address.lines().size > 1) {
+            return VerificationResult.Invalid.Address
+        }
+
+        // If both are 0 do nothing else check start is smaller than end or return error
+        if (!(
+            protoQrCodePayload.locationData.startTimestamp == 0L &&
+                protoQrCodePayload.locationData.endTimestamp == 0L
+            )
+        ) {
+            if (protoQrCodePayload.locationData.startTimestamp > protoQrCodePayload.locationData.endTimestamp) {
+                return VerificationResult.Invalid.StartEndTime
+            }
+        }
+
+        if (traceLocation.cryptographicSeed.size != CROWD_NOTIFIER_CRYPTO_SEED_LENGTH) {
+            return VerificationResult.Invalid.CryptographicSeed
+        }
+
+        return VerificationResult.Valid(
+            VerifiedTraceLocation(protoQrCodePayload)
+        )
+    }
+
+    sealed class VerificationResult {
+        data class Valid(val verifiedTraceLocation: VerifiedTraceLocation) : VerificationResult()
+
+        sealed class Invalid(@StringRes val errorTextRes: Int) : VerificationResult() {
+            object Description : Invalid(R.string.trace_location_checkins_qr_code_invalid_description)
+            object Address : Invalid(R.string.trace_location_checkins_qr_code_invalid_address)
+            object StartEndTime : Invalid(R.string.trace_location_checkins_qr_code_invalid_times)
+            object CryptographicSeed :
+                Invalid(R.string.trace_location_checkins_qr_code_invalid_cryptographic_seed)
+        }
+    }
+
+    companion object {
+        private const val CROWD_NOTIFIER_CRYPTO_SEED_LENGTH = 16
+        private const val QR_CODE_DESCRIPTION_MAX_LENGTH = 100
+        private const val QR_CODE_ADDRESS_MAX_LENGTH = 100
+    }
+}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/attendee/checkins/CheckInEvent.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/attendee/checkins/CheckInEvent.kt
index e39108ce29600a74f267bbf33eca0ed36ff2bb96..a8c0aba5198cd1c7f7bfa98a90e34dea8566ce5c 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/attendee/checkins/CheckInEvent.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/attendee/checkins/CheckInEvent.kt
@@ -1,5 +1,6 @@
 package de.rki.coronawarnapp.ui.eventregistration.attendee.checkins
 
+import androidx.annotation.StringRes
 import de.rki.coronawarnapp.eventregistration.checkins.CheckIn
 import de.rki.coronawarnapp.eventregistration.checkins.qrcode.VerifiedTraceLocation
 
@@ -11,6 +12,8 @@ sealed class CheckInEvent {
 
     data class ConfirmCheckIn(val verifiedTraceLocation: VerifiedTraceLocation) : CheckInEvent()
 
+    data class InvalidQrCode(@StringRes val errorTextRes: Int) : CheckInEvent()
+
     data class ConfirmCheckInWithoutHistory(val verifiedTraceLocation: VerifiedTraceLocation) : CheckInEvent()
 
     data class EditCheckIn(val checkInId: Long, val position: Int) : CheckInEvent()
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/attendee/checkins/CheckInsFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/attendee/checkins/CheckInsFragment.kt
index 5b9a042b7d75a2fabf76e7a0d616a15c71b204b5..d198e93cc2b4ac82228cc1215d73cec574e7fa7f 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/attendee/checkins/CheckInsFragment.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/attendee/checkins/CheckInsFragment.kt
@@ -7,6 +7,7 @@ import android.os.Bundle
 import android.provider.Settings
 import android.view.View
 import android.widget.Toast
+import androidx.annotation.StringRes
 import androidx.appcompat.app.AlertDialog
 import androidx.appcompat.widget.Toolbar
 import androidx.core.net.toUri
@@ -16,6 +17,7 @@ import androidx.navigation.fragment.FragmentNavigatorExtras
 import androidx.navigation.fragment.findNavController
 import androidx.navigation.fragment.navArgs
 import androidx.recyclerview.widget.DefaultItemAnimator
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
 import com.google.android.material.transition.Hold
 import com.google.android.material.transition.MaterialSharedAxis
 import de.rki.coronawarnapp.BuildConfig
@@ -38,7 +40,6 @@ import de.rki.coronawarnapp.util.ui.viewBindingLazy
 import de.rki.coronawarnapp.util.viewmodel.CWAViewModelFactoryProvider
 import de.rki.coronawarnapp.util.viewmodel.cwaViewModelsAssisted
 import timber.log.Timber
-import java.lang.Exception
 import java.net.URLEncoder
 import javax.inject.Inject
 
@@ -98,6 +99,8 @@ class CheckInsFragment : Fragment(R.layout.trace_location_attendee_checkins_frag
                 )
             }
 
+            is CheckInEvent.InvalidQrCode -> showInvalidQrCodeInformation(event.errorTextRes)
+
             is CheckInEvent.ConfirmCheckInWithoutHistory -> doNavigate(
                 CheckInsFragmentDirections.actionCheckInsFragmentToConfirmCheckInFragmentCleanHistory(
                     verifiedTraceLocation = event.verifiedTraceLocation
@@ -132,6 +135,13 @@ class CheckInsFragment : Fragment(R.layout.trace_location_attendee_checkins_frag
         }
     }
 
+    private fun showInvalidQrCodeInformation(@StringRes errorTextRes: Int) =
+        MaterialAlertDialogBuilder(requireContext()).apply {
+            setTitle(R.string.errors_generic_headline)
+            setMessage(errorTextRes)
+            setPositiveButton(R.string.errors_generic_button_positive) { _, _ -> }
+        }.show()
+
     private fun updateViews(items: List<CheckInsItem>) {
         checkInsAdapter.update(items)
         binding.apply {
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/attendee/checkins/CheckInsViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/attendee/checkins/CheckInsViewModel.kt
index f80b589f139c25a5a4f4c9f0d3811bc119e146aa..94c98114e6d18bbff7bd7932ba116ef723bb7684 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/attendee/checkins/CheckInsViewModel.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/attendee/checkins/CheckInsViewModel.kt
@@ -9,7 +9,7 @@ import dagger.assisted.AssistedInject
 import de.rki.coronawarnapp.eventregistration.checkins.CheckIn
 import de.rki.coronawarnapp.eventregistration.checkins.CheckInRepository
 import de.rki.coronawarnapp.eventregistration.checkins.qrcode.QRCodeUriParser
-import de.rki.coronawarnapp.eventregistration.checkins.qrcode.VerifiedTraceLocation
+import de.rki.coronawarnapp.eventregistration.checkins.qrcode.TraceLocationVerifier
 import de.rki.coronawarnapp.exception.ExceptionCategory
 import de.rki.coronawarnapp.exception.reporting.report
 import de.rki.coronawarnapp.presencetracing.checkins.checkout.CheckOutHandler
@@ -28,6 +28,7 @@ import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.combine
 import timber.log.Timber
 
+@Suppress("LongParameterList")
 class CheckInsViewModel @AssistedInject constructor(
     @Assisted private val savedState: SavedStateHandle,
     @Assisted private val deepLink: String?,
@@ -37,7 +38,8 @@ class CheckInsViewModel @AssistedInject constructor(
     private val qrCodeUriParser: QRCodeUriParser,
     private val checkInsRepository: CheckInRepository,
     private val checkOutHandler: CheckOutHandler,
-    private val cameraPermissionProvider: CameraPermissionProvider
+    private val cameraPermissionProvider: CameraPermissionProvider,
+    private val traceLocationVerifier: TraceLocationVerifier
 ) : CWAViewModel(dispatcherProvider) {
 
     val events = SingleLiveEvent<CheckInEvent>()
@@ -143,13 +145,16 @@ class CheckInsViewModel @AssistedInject constructor(
         try {
             Timber.i("uri: $uri")
             val qrCodePayload = qrCodeUriParser.getQrCodePayload(uri)
-            val verifiedTraceLocation = VerifiedTraceLocation(qrCodePayload)
-            events.postValue(
-                if (cleanHistory)
-                    CheckInEvent.ConfirmCheckInWithoutHistory(verifiedTraceLocation)
-                else
-                    CheckInEvent.ConfirmCheckIn(verifiedTraceLocation)
-            )
+            when (val verifyResult = traceLocationVerifier.verifyTraceLocation(qrCodePayload)) {
+                is TraceLocationVerifier.VerificationResult.Valid -> events.postValue(
+                    if (cleanHistory)
+                        CheckInEvent.ConfirmCheckInWithoutHistory(verifyResult.verifiedTraceLocation)
+                    else
+                        CheckInEvent.ConfirmCheckIn(verifyResult.verifiedTraceLocation)
+                )
+                is TraceLocationVerifier.VerificationResult.Invalid ->
+                    events.postValue(CheckInEvent.InvalidQrCode(verifyResult.errorTextRes))
+            }
         } catch (e: Exception) {
             Timber.d(e, "TraceLocation verification failed")
             e.report(ExceptionCategory.INTERNAL)
diff --git a/Corona-Warn-App/src/main/res/values-de/event_registration_strings.xml b/Corona-Warn-App/src/main/res/values-de/event_registration_strings.xml
index 732c3f2c57841116a81ebae569f4bdc3f7defcef..758b6ca6e8c166dd4540c89b14c42010f5ffb433 100644
--- a/Corona-Warn-App/src/main/res/values-de/event_registration_strings.xml
+++ b/Corona-Warn-App/src/main/res/values-de/event_registration_strings.xml
@@ -259,4 +259,14 @@
     <!-- XBUT: Organizer Flow : Title for save as template button -->
     <string name="trace_location_event_detail_save_as_template_button">"Als Vorlage verwenden"</string>
 
+    <!-- Qr Code Validation Messages -->
+    <!-- XTXT: My check-ins: qr code validation wrong description field -->
+    <string name="trace_location_checkins_qr_code_invalid_description">"Ungültiger QR-Code verhindert das Einchecken. Die verantwortliche Stelle muss einen neuen QR-Code generieren (Fehlercode INVALID_DESCRIPTION)."</string>
+    <!-- XTXT: My check-ins: qr code validation wrong address field -->
+    <string name="trace_location_checkins_qr_code_invalid_address">"Ungültiger QR-Code verhindert das Einchecken. Die verantwortliche Stelle muss einen neuen QR-Code generieren (Fehlercode INVALID_ADDRESS)."</string>
+    <!-- XTXT: My check-ins: qr code validation wrong start end time field -->
+    <string name="trace_location_checkins_qr_code_invalid_times">"Ungültiger QR-Code verhindert das Einchecken. Die verantwortliche Stelle muss einen neuen QR-Code generieren (Fehlercode INVALID_TIMESTAMPS)."</string>
+    <!-- XTXT: My check-ins: qr code validation wrong cryptographic seed field -->
+    <string name="trace_location_checkins_qr_code_invalid_cryptographic_seed">"Ungültiger QR-Code verhindert das Einchecken. Die verantwortliche Stelle muss einen neuen QR-Code generieren (Fehlercode INVALID_CRYPTO_SEED)."</string>
+
 </resources>
diff --git a/Corona-Warn-App/src/main/res/values/event_registration_strings.xml b/Corona-Warn-App/src/main/res/values/event_registration_strings.xml
index 453cda2241e0d14ef22be58292a245358b2cc354..9896181c86dbe91f97783d12c58501d797371a41 100644
--- a/Corona-Warn-App/src/main/res/values/event_registration_strings.xml
+++ b/Corona-Warn-App/src/main/res/values/event_registration_strings.xml
@@ -257,4 +257,14 @@
     <!-- XBUT: Organizer Flow : Title for save as template button -->
     <string name="trace_location_event_detail_save_as_template_button">"Use as Template"</string>
 
+    <!-- Qr Code Validation Messages -->
+    <!-- XTXT: My check-ins: qr code validation wrong description field -->
+    <string name="trace_location_checkins_qr_code_invalid_description">"Ungültiger QR-Code verhindert das Einchecken. Die verantwortliche Stelle muss einen neuen QR-Code generieren (Fehlercode INVALID_DESCRIPTION)."</string>
+    <!-- XTXT: My check-ins: qr code validation wrong address field -->
+    <string name="trace_location_checkins_qr_code_invalid_address">"Ungültiger QR-Code verhindert das Einchecken. Die verantwortliche Stelle muss einen neuen QR-Code generieren (Fehlercode INVALID_ADDRESS)."</string>
+    <!-- XTXT: My check-ins: qr code validation wrong start end time field -->
+    <string name="trace_location_checkins_qr_code_invalid_times">"Ungültiger QR-Code verhindert das Einchecken. Die verantwortliche Stelle muss einen neuen QR-Code generieren (Fehlercode INVALID_TIMESTAMPS)."</string>
+    <!-- XTXT: My check-ins: qr code validation wrong cryptographic seed field -->
+    <string name="trace_location_checkins_qr_code_invalid_cryptographic_seed">"Ungültiger QR-Code verhindert das Einchecken. Die verantwortliche Stelle muss einen neuen QR-Code generieren (Fehlercode INVALID_CRYPTO_SEED)."</string>
+
 </resources>
\ No newline at end of file
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/InvalidQRCodeProvider.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/InvalidQRCodeProvider.kt
new file mode 100644
index 0000000000000000000000000000000000000000..6d8df6b978065dd082d5a9d2825af00e11df9a88
--- /dev/null
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/InvalidQRCodeProvider.kt
@@ -0,0 +1,148 @@
+package de.rki.coronawarnapp.eventregistration.checkins.qrcode
+
+import de.rki.coronawarnapp.server.protocols.internal.pt.TraceLocationOuterClass
+import de.rki.coronawarnapp.util.toProtoByteString
+import okio.ByteString.Companion.decodeBase64
+import org.junit.jupiter.api.extension.ExtensionContext
+import org.junit.jupiter.params.provider.Arguments
+import org.junit.jupiter.params.provider.ArgumentsProvider
+import java.util.stream.Stream
+
+class InvalidQRCodeProvider : ArgumentsProvider {
+    private fun baseValidQrCodeBuilder(): TraceLocationOuterClass.QRCodePayload.Builder =
+        TraceLocationOuterClass.QRCodePayload.newBuilder()
+            .setVersion(1)
+            .setCrowdNotifierData(
+                TraceLocationOuterClass.CrowdNotifierData.newBuilder()
+                    .setCryptographicSeed(CRYPTOGRAPHIC_SEED.decodeBase64()!!.toProtoByteString())
+                    .setPublicKey(PUB_KEY.decodeBase64()!!.toProtoByteString())
+                    .setVersion(1)
+            )
+            .setVendorData("CAEQARgK".decodeBase64()!!.toProtoByteString())
+            .setLocationData(
+                TraceLocationOuterClass.TraceLocation.newBuilder()
+                    .setDescription("Icecream Shop")
+                    .setAddress("Main Street 1")
+                    .setVersion(1)
+                    .build()
+            )
+
+    private fun baseValidLocationData(): TraceLocationOuterClass.TraceLocation.Builder =
+        TraceLocationOuterClass.TraceLocation.newBuilder()
+            .setDescription("Icecream Shop")
+            .setAddress("Main Street 1")
+            .setVersion(1)
+
+    override fun provideArguments(context: ExtensionContext?): Stream<out Arguments> {
+        return Stream.of(
+            Arguments.of(
+                baseValidQrCodeBuilder()
+                    .setLocationData(
+                        baseValidLocationData()
+                            .setStartTimestamp(2687991)
+                            .build()
+                    ).build(),
+                TraceLocationVerifier.VerificationResult.Invalid.StartEndTime
+            ),
+            Arguments.of(
+                baseValidQrCodeBuilder()
+                    .setLocationData(
+                        baseValidLocationData()
+                            .setStartTimestamp(2687991)
+                            .setEndTimestamp(2387991)
+                            .build()
+                    ).build(),
+                TraceLocationVerifier.VerificationResult.Invalid.StartEndTime
+            ),
+            Arguments.of(
+                baseValidQrCodeBuilder()
+                    .setLocationData(
+                        baseValidLocationData()
+                            .setDescription("")
+                            .build()
+                    ).build(),
+                TraceLocationVerifier.VerificationResult.Invalid.Description
+            ),
+            Arguments.of(
+                baseValidQrCodeBuilder()
+                    .setLocationData(
+                        baseValidLocationData()
+                            .clearDescription()
+                            .build()
+                    ).build(),
+                TraceLocationVerifier.VerificationResult.Invalid.Description
+            ),
+            Arguments.of(
+                baseValidQrCodeBuilder()
+                    .setLocationData(
+                        baseValidLocationData()
+                            .setDescription((0..101).joinToString { "a" })
+                            .build()
+                    ).build(),
+                TraceLocationVerifier.VerificationResult.Invalid.Description
+            ),
+            Arguments.of(
+                baseValidQrCodeBuilder()
+                    .setLocationData(
+                        baseValidLocationData()
+                            .setDescription("A \n B")
+                            .build()
+                    ).build(),
+                TraceLocationVerifier.VerificationResult.Invalid.Description
+            ),
+            Arguments.of(
+                baseValidQrCodeBuilder()
+                    .setLocationData(
+                        baseValidLocationData()
+                            .setAddress("")
+                            .build()
+                    ).build(),
+                TraceLocationVerifier.VerificationResult.Invalid.Address
+            ),
+            Arguments.of(
+                baseValidQrCodeBuilder()
+                    .setLocationData(
+                        baseValidLocationData()
+                            .clearAddress()
+                            .build()
+                    ).build(),
+                TraceLocationVerifier.VerificationResult.Invalid.Address
+            ),
+            Arguments.of(
+                baseValidQrCodeBuilder()
+                    .setLocationData(
+                        baseValidLocationData()
+                            .setAddress((0..101).joinToString { "a" })
+                            .build()
+                    ).build(),
+                TraceLocationVerifier.VerificationResult.Invalid.Address
+            ),
+            Arguments.of(
+                baseValidQrCodeBuilder()
+                    .setLocationData(
+                        baseValidLocationData()
+                            .setAddress("A \n B")
+                            .build()
+                    ).build(),
+                TraceLocationVerifier.VerificationResult.Invalid.Address
+            ),
+            Arguments.of(
+                baseValidQrCodeBuilder()
+                    .setCrowdNotifierData(
+                        TraceLocationOuterClass.CrowdNotifierData.newBuilder()
+                            .setCryptographicSeed("WNlQ==".decodeBase64()!!.toProtoByteString())
+                            .setPublicKey(PUB_KEY.decodeBase64()!!.toProtoByteString())
+                            .setVersion(1)
+                    ).build(),
+                TraceLocationVerifier.VerificationResult.Invalid.CryptographicSeed
+            )
+        )
+    }
+
+    companion object {
+        const val CRYPTOGRAPHIC_SEED = "zveDikIfwAXWqI6h4dWNlQ=="
+        const val PUB_KEY =
+            "OMTa6eYSiaDv8lW13xdYEvGHOZ1EYTiFSxt51HEoPCD7CNnvCUiIYPhax1MpkN0UfNClCm9ZWYy0JH01CDVD9" +
+                "eq+voxQ1EcFJQkEIujVwoCNK0MNGuDK1ayjGxeDc4UD"
+    }
+}
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/TraceLocationVerifierTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/TraceLocationVerifierTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..1bc7865431213f233211fd4eecaa641f8cc16586
--- /dev/null
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/TraceLocationVerifierTest.kt
@@ -0,0 +1,32 @@
+package de.rki.coronawarnapp.eventregistration.checkins.qrcode
+
+import de.rki.coronawarnapp.server.protocols.internal.pt.TraceLocationOuterClass
+import io.kotest.matchers.shouldBe
+import org.junit.jupiter.params.ParameterizedTest
+import org.junit.jupiter.params.provider.ArgumentsSource
+import testhelpers.BaseTest
+
+class TraceLocationVerifierTest : BaseTest() {
+    fun createInstance() = TraceLocationVerifier()
+
+    @ParameterizedTest
+    @ArgumentsSource(ValidQRCodeProvider::class)
+    fun `Valid QR Codes`(
+        protoQrCodePayload: TraceLocationOuterClass.QRCodePayload
+    ) {
+        val validationResult = createInstance().verifyTraceLocation(protoQrCodePayload)
+
+        (validationResult is TraceLocationVerifier.VerificationResult.Valid) shouldBe true
+    }
+
+    @ParameterizedTest
+    @ArgumentsSource(InvalidQRCodeProvider::class)
+    fun `Invalid QR Codes`(
+        protoQrCodePayload: TraceLocationOuterClass.QRCodePayload,
+        expectedFailure: TraceLocationVerifier.VerificationResult.Invalid
+    ) {
+        val validationResult = createInstance().verifyTraceLocation(protoQrCodePayload)
+
+        validationResult shouldBe expectedFailure
+    }
+}
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/ValidQRCodeProvider.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/ValidQRCodeProvider.kt
new file mode 100644
index 0000000000000000000000000000000000000000..bd08d284659adf109ec01c0b29834815631f01d1
--- /dev/null
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/ValidQRCodeProvider.kt
@@ -0,0 +1,104 @@
+package de.rki.coronawarnapp.eventregistration.checkins.qrcode
+
+import de.rki.coronawarnapp.server.protocols.internal.pt.TraceLocationOuterClass
+import de.rki.coronawarnapp.util.toProtoByteString
+import okio.ByteString.Companion.decodeBase64
+import org.junit.jupiter.api.extension.ExtensionContext
+import org.junit.jupiter.params.provider.Arguments
+import org.junit.jupiter.params.provider.ArgumentsProvider
+import java.util.stream.Stream
+
+class ValidQRCodeProvider : ArgumentsProvider {
+    override fun provideArguments(context: ExtensionContext?): Stream<out Arguments> {
+        return Stream.of(
+            Arguments.of(
+                TraceLocationOuterClass.QRCodePayload.newBuilder()
+                    .setVersion(1)
+                    .setCrowdNotifierData(
+                        TraceLocationOuterClass.CrowdNotifierData.newBuilder()
+                            .setCryptographicSeed(CRYPTOGRAPHIC_SEED.decodeBase64()!!.toProtoByteString())
+                            .setPublicKey(PUB_KEY.decodeBase64()!!.toProtoByteString())
+                            .setVersion(1)
+                    )
+                    .setVendorData("CAEQAg==".decodeBase64()!!.toProtoByteString())
+                    .setLocationData(
+                        TraceLocationOuterClass.TraceLocation.newBuilder()
+                            .setDescription("My Birthday Party")
+                            .setAddress("at my place")
+                            .setStartTimestamp(2687955)
+                            .setEndTimestamp(2687991)
+                            .setVersion(1)
+                            .build()
+                    )
+                    .build()
+            ),
+            Arguments.of(
+                TraceLocationOuterClass.QRCodePayload.newBuilder()
+                    .setVersion(1)
+                    .setCrowdNotifierData(
+                        TraceLocationOuterClass.CrowdNotifierData.newBuilder()
+                            .setCryptographicSeed(CRYPTOGRAPHIC_SEED.decodeBase64()!!.toProtoByteString())
+                            .setPublicKey(PUB_KEY.decodeBase64()!!.toProtoByteString())
+                            .setVersion(1)
+                    )
+                    .setVendorData("CAEQAg==".decodeBase64()!!.toProtoByteString())
+                    .setLocationData(
+                        TraceLocationOuterClass.TraceLocation.newBuilder()
+                            .setDescription("My Birthday Party")
+                            .setAddress("at my place")
+                            .setStartTimestamp(2687991)
+                            .setEndTimestamp(2687991)
+                            .setVersion(1)
+                            .build()
+                    )
+                    .build()
+            ),
+            Arguments.of(
+                TraceLocationOuterClass.QRCodePayload.newBuilder()
+                    .setVersion(1)
+                    .setCrowdNotifierData(
+                        TraceLocationOuterClass.CrowdNotifierData.newBuilder()
+                            .setCryptographicSeed(CRYPTOGRAPHIC_SEED.decodeBase64()!!.toProtoByteString())
+                            .setPublicKey(PUB_KEY.decodeBase64()!!.toProtoByteString())
+                            .setVersion(1)
+                    )
+                    .setVendorData("CAEQAg==".decodeBase64()!!.toProtoByteString())
+                    .setLocationData(
+                        TraceLocationOuterClass.TraceLocation.newBuilder()
+                            .setDescription("My Birthday Party")
+                            .setAddress("at my place")
+                            .setEndTimestamp(2687991)
+                            .setVersion(1)
+                            .build()
+                    )
+                    .build()
+            ),
+            Arguments.of(
+                TraceLocationOuterClass.QRCodePayload.newBuilder()
+                    .setVersion(1)
+                    .setCrowdNotifierData(
+                        TraceLocationOuterClass.CrowdNotifierData.newBuilder()
+                            .setCryptographicSeed(CRYPTOGRAPHIC_SEED.decodeBase64()!!.toProtoByteString())
+                            .setPublicKey(PUB_KEY.decodeBase64()!!.toProtoByteString())
+                            .setVersion(1)
+                    )
+                    .setVendorData("CAEQARgK".decodeBase64()!!.toProtoByteString())
+                    .setLocationData(
+                        TraceLocationOuterClass.TraceLocation.newBuilder()
+                            .setDescription("Icecream Shop")
+                            .setAddress("Main Street 1")
+                            .setVersion(1)
+                            .build()
+                    )
+                    .build()
+            )
+        )
+    }
+
+    companion object {
+        const val CRYPTOGRAPHIC_SEED = "zveDikIfwAXWqI6h4dWNlQ=="
+        const val PUB_KEY =
+            "OMTa6eYSiaDv8lW13xdYEvGHOZ1EYTiFSxt51HEoPCD7CNnvCUiIYPhax1MpkN0UfNClCm9ZWYy0JH01CDVD9" +
+                "eq+voxQ1EcFJQkEIujVwoCNK0MNGuDK1ayjGxeDc4UD"
+    }
+}
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/eventregistration/attendee/checkins/CheckInsViewModelTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/eventregistration/attendee/checkins/CheckInsViewModelTest.kt
index 1d0e83df047be9ac627d9f6da5b08c377055dadb..7efbed5de4b31e4457ff92bac769a757a49b9eaa 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/eventregistration/attendee/checkins/CheckInsViewModelTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/eventregistration/attendee/checkins/CheckInsViewModelTest.kt
@@ -4,6 +4,7 @@ import androidx.lifecycle.SavedStateHandle
 import de.rki.coronawarnapp.eventregistration.checkins.CheckIn
 import de.rki.coronawarnapp.eventregistration.checkins.CheckInRepository
 import de.rki.coronawarnapp.eventregistration.checkins.qrcode.QRCodeUriParser
+import de.rki.coronawarnapp.eventregistration.checkins.qrcode.TraceLocationVerifier
 import de.rki.coronawarnapp.presencetracing.checkins.checkout.CheckOutHandler
 import de.rki.coronawarnapp.server.protocols.internal.pt.TraceLocationOuterClass
 import de.rki.coronawarnapp.ui.eventregistration.attendee.checkins.items.ActiveCheckInVH
@@ -41,6 +42,7 @@ class CheckInsViewModelTest : BaseTest() {
     @MockK lateinit var checkInsRepository: CheckInRepository
     @MockK lateinit var checkOutHandler: CheckOutHandler
     @MockK lateinit var cameraPermissionProvider: CameraPermissionProvider
+    @MockK lateinit var traceLocationVerifier: TraceLocationVerifier
 
     @BeforeEach
     fun setup() {
@@ -48,6 +50,8 @@ class CheckInsViewModelTest : BaseTest() {
         every { savedState.set(any(), any<String>()) } just Runs
         every { checkInsRepository.checkInsWithinRetention } returns flowOf()
         every { cameraPermissionProvider.deniedPermanently } returns flowOf(false)
+        every { traceLocationVerifier.verifyTraceLocation(any()) } returns
+            TraceLocationVerifier.VerificationResult.Valid(mockk())
     }
 
     @Test
@@ -186,6 +190,7 @@ class CheckInsViewModelTest : BaseTest() {
             checkInsRepository = checkInsRepository,
             checkOutHandler = checkOutHandler,
             cameraPermissionProvider = cameraPermissionProvider,
+            traceLocationVerifier = traceLocationVerifier,
             cleanHistory = false
         )