Skip to content

Commit

Permalink
Make PresentationSession optional. (#336)
Browse files Browse the repository at this point in the history
With PresentationSession now in the 'legacy' package it would be
helpful if an application could just pass a KeyPair and PublicKey
which can be used for mdoc session authentication.

Also remove EC Curve constants from Constants class since these are
already available in KeystoreEngine interface

Also add docs for NfcEngagementHelper and QrEngagementHelper.

Test: All unit tests pass.
Test: Manully tested.
  • Loading branch information
davidz25 authored Aug 10, 2023
1 parent 3c7a7d5 commit 982ad4b
Show file tree
Hide file tree
Showing 18 changed files with 484 additions and 222 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ import com.android.identity.android.mdoc.transport.DataTransport
import com.android.identity.android.mdoc.deviceretrieval.DeviceRetrievalHelper
import com.android.identity.android.legacy.PresentationSession
import com.android.identity.android.mdoc.engagement.QrEngagementHelper
import com.android.identity.keystore.KeystoreEngine
import com.android.mdl.app.util.log
import com.android.mdl.app.util.mainExecutor
import java.security.PublicKey

class QrCommunicationSetup(
private val context: Context,
Expand Down Expand Up @@ -44,7 +46,7 @@ class QrCommunicationSetup(
context,
deviceRetrievalHelperListener,
context.mainExecutor(),
session
session.ephemeralKeyPair
)
builder.useForwardEngagement(
transport,
Expand All @@ -63,6 +65,11 @@ class QrCommunicationSetup(
}

private val deviceRetrievalHelperListener = object : DeviceRetrievalHelper.Listener {
override fun onEReaderKeyReceived(eReaderKey: PublicKey) {
log("DeviceRetrievalHelper Listener (QR): OnEReaderKeyReceived")
session.setSessionTranscript(deviceRetrievalHelper!!.sessionTranscript)
session.setReaderEphemeralPublicKey(eReaderKey)
}

override fun onDeviceRequest(deviceRequestBytes: ByteArray) {
log("DeviceRetrievalHelper Listener (QR): OnDeviceRequest")
Expand Down Expand Up @@ -90,7 +97,7 @@ class QrCommunicationSetup(
qrEngagement =
QrEngagementHelper.Builder(
context,
session,
session.ephemeralKeyPair.public,
connectionSetup.getConnectionOptions(),
qrEngagementListener,
context.mainExecutor())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import com.android.identity.android.mdoc.deviceretrieval.DeviceRetrievalHelper
import com.android.identity.android.legacy.PresentationSession
import com.android.mdl.app.util.log
import com.android.mdl.app.util.mainExecutor
import java.security.PublicKey

class ReverseQrCommunicationSetup(
private val context: Context,
Expand All @@ -22,6 +23,11 @@ class ReverseQrCommunicationSetup(
private val session = SessionSetup(CredentialStore(context)).createSession()
private val connectionSetup = ConnectionSetup(context)
private val presentationListener = object : DeviceRetrievalHelper.Listener {
override fun onEReaderKeyReceived(eReaderKey: PublicKey) {
log("DeviceRetrievalHelper Listener (QR): OnEReaderKeyReceived")
session.setSessionTranscript(presentation!!.sessionTranscript)
session.setReaderEphemeralPublicKey(eReaderKey)
}

override fun onDeviceRequest(deviceRequestBytes: ByteArray) {
onNewRequest(deviceRequestBytes)
Expand Down Expand Up @@ -72,8 +78,9 @@ class ReverseQrCommunicationSetup(
context,
presentationListener,
context.mainExecutor(),
session
).useReverseEngagement(transport, encodedReaderEngagement, origins)
session.ephemeralKeyPair
)
builder.useReverseEngagement(transport, encodedReaderEngagement, origins)
presentation = builder.build()
onPresentationReady(session, presentation!!)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import com.android.mdl.app.transfer.ConnectionSetup
import com.android.mdl.app.transfer.CredentialStore
import com.android.mdl.app.transfer.SessionSetup
import com.android.mdl.app.transfer.TransferManager
import java.security.PublicKey


class NfcEngagementHandler : HostApduService() {
Expand Down Expand Up @@ -78,7 +79,7 @@ class NfcEngagementHandler : HostApduService() {
applicationContext,
presentationListener,
applicationContext.mainExecutor(),
session
session.ephemeralKeyPair
)
builder.useForwardEngagement(
transport,
Expand All @@ -99,6 +100,11 @@ class NfcEngagementHandler : HostApduService() {
}

private val presentationListener = object : DeviceRetrievalHelper.Listener {
override fun onEReaderKeyReceived(eReaderKey: PublicKey) {
log("DeviceRetrievalHelper Listener (NFC): OnEReaderKeyReceived")
session.setSessionTranscript(presentation!!.sessionTranscript)
session.setReaderEphemeralPublicKey(eReaderKey)
}

override fun onDeviceRequest(deviceRequestBytes: ByteArray) {
log("Presentation Listener: OnDeviceRequest")
Expand Down Expand Up @@ -127,7 +133,7 @@ class NfcEngagementHandler : HostApduService() {
val connectionSetup = ConnectionSetup(applicationContext)
val builder = NfcEngagementHelper.Builder(
applicationContext,
session,
session.ephemeralKeyPair.public,
connectionSetup.getConnectionOptions(),
nfcEngagementListener,
applicationContext.mainExecutor())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ public void dynamicAuthTest() throws Exception {
+ "}",
pretty);

KeyPair readerEphemeralKeyPair = Utility.createEphemeralKeyPair(Constants.EC_CURVE_P256);
KeyPair readerEphemeralKeyPair = Util.createEphemeralKeyPair(Constants.EC_CURVE_P256);

credential = store.getCredentialByName(credentialName,
IdentityCredentialStore.CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256);
Expand Down Expand Up @@ -647,7 +647,7 @@ public void dynamicAuthWithExpirationTest() throws Exception {
IdentityCredential tc = store.getCredentialByName(credentialName,
IdentityCredentialStore.CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256);
KeyPair ekp = tc.createEphemeralKeyPair();
KeyPair rekp = Utility.createEphemeralKeyPair(Constants.EC_CURVE_P256);
KeyPair rekp = Util.createEphemeralKeyPair(Constants.EC_CURVE_P256);
tc.setReaderEphemeralPublicKey(rekp.getPublic());
tc.setSessionTranscript(Util.buildSessionTranscript(ekp));
Map<String, Collection<String>> etr = new LinkedHashMap<>();
Expand Down Expand Up @@ -676,7 +676,7 @@ public void dynamicAuthWithExpirationTest() throws Exception {
IdentityCredential tc = store.getCredentialByName(credentialName,
IdentityCredentialStore.CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256);
KeyPair ekp = tc.createEphemeralKeyPair();
KeyPair rekp = Utility.createEphemeralKeyPair(Constants.EC_CURVE_P256);
KeyPair rekp = Util.createEphemeralKeyPair(Constants.EC_CURVE_P256);
tc.setReaderEphemeralPublicKey(rekp.getPublic());
tc.setSessionTranscript(Util.buildSessionTranscript(ekp));
Map<String, Collection<String>> etr = new LinkedHashMap<>();
Expand Down Expand Up @@ -704,7 +704,7 @@ public void dynamicAuthWithExpirationTest() throws Exception {
IdentityCredentialStore.CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256);
tc.setAllowUsingExpiredKeys(true); // <-- this is the call that makes the difference!
KeyPair ekp = tc.createEphemeralKeyPair();
KeyPair rekp = Utility.createEphemeralKeyPair(Constants.EC_CURVE_P256);
KeyPair rekp = Util.createEphemeralKeyPair(Constants.EC_CURVE_P256);
tc.setReaderEphemeralPublicKey(rekp.getPublic());
tc.setSessionTranscript(Util.buildSessionTranscript(ekp));
Map<String, Collection<String>> etr = new LinkedHashMap<>();
Expand Down Expand Up @@ -776,7 +776,7 @@ public void dynamicAuthMinValidTimeTest() throws Exception {
IdentityCredential tc = store.getCredentialByName(credentialName,
IdentityCredentialStore.CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256);
KeyPair ekp = tc.createEphemeralKeyPair();
KeyPair rekp = Utility.createEphemeralKeyPair(Constants.EC_CURVE_P256);
KeyPair rekp = Util.createEphemeralKeyPair(Constants.EC_CURVE_P256);
tc.setReaderEphemeralPublicKey(rekp.getPublic());
tc.setSessionTranscript(Util.buildSessionTranscript(ekp));
Map<String, Collection<String>> etr = new LinkedHashMap<>();
Expand Down Expand Up @@ -808,7 +808,7 @@ public void dynamicAuthMinValidTimeTest() throws Exception {
IdentityCredential tc = store.getCredentialByName(credentialName,
IdentityCredentialStore.CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256);
KeyPair ekp = tc.createEphemeralKeyPair();
KeyPair rekp = Utility.createEphemeralKeyPair(Constants.EC_CURVE_P256);
KeyPair rekp = Util.createEphemeralKeyPair(Constants.EC_CURVE_P256);
tc.setReaderEphemeralPublicKey(rekp.getPublic());
tc.setSessionTranscript(Util.buildSessionTranscript(ekp));
Map<String, Collection<String>> etr = new LinkedHashMap<>();
Expand Down Expand Up @@ -857,7 +857,7 @@ public void dynamicAuthMinValidTimeTest() throws Exception {
IdentityCredential tc = store.getCredentialByName(credentialName,
IdentityCredentialStore.CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256);
KeyPair ekp = tc.createEphemeralKeyPair();
KeyPair rekp = Utility.createEphemeralKeyPair(Constants.EC_CURVE_P256);
KeyPair rekp = Util.createEphemeralKeyPair(Constants.EC_CURVE_P256);
tc.setReaderEphemeralPublicKey(rekp.getPublic());
tc.setSessionTranscript(Util.buildSessionTranscript(ekp));
Map<String, Collection<String>> etr = new LinkedHashMap<>();
Expand Down Expand Up @@ -888,7 +888,7 @@ public void dynamicAuthMinValidTimeTest() throws Exception {
IdentityCredential tc = store.getCredentialByName(credentialName,
IdentityCredentialStore.CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256);
KeyPair ekp = tc.createEphemeralKeyPair();
KeyPair rekp = Utility.createEphemeralKeyPair(Constants.EC_CURVE_P256);
KeyPair rekp = Util.createEphemeralKeyPair(Constants.EC_CURVE_P256);
tc.setReaderEphemeralPublicKey(rekp.getPublic());
tc.setSessionTranscript(Util.buildSessionTranscript(ekp));
Map<String, Collection<String>> etr = new LinkedHashMap<>();
Expand Down Expand Up @@ -916,7 +916,7 @@ public void dynamicAuthMinValidTimeTest() throws Exception {
IdentityCredentialStore.CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256);
tc.setAllowUsingExpiredKeys(true); // <-- this is the call that makes the difference!
KeyPair ekp = tc.createEphemeralKeyPair();
KeyPair rekp = Utility.createEphemeralKeyPair(Constants.EC_CURVE_P256);
KeyPair rekp = Util.createEphemeralKeyPair(Constants.EC_CURVE_P256);
tc.setReaderEphemeralPublicKey(rekp.getPublic());
tc.setSessionTranscript(Util.buildSessionTranscript(ekp));
Map<String, Collection<String>> etr = new LinkedHashMap<>();
Expand Down Expand Up @@ -1040,7 +1040,7 @@ public void dynamicAuthMultipleGetEntries() throws Exception {
Map<String, Collection<String>> entriesToRequest = new LinkedHashMap<>();
entriesToRequest.put("org.iso.18013-5.2019", Arrays.asList("First name", "Last name"));
KeyPair ephemeralKeyPair = credential.createEphemeralKeyPair();
KeyPair readerEphemeralKeyPair = Utility.createEphemeralKeyPair(Constants.EC_CURVE_P256);
KeyPair readerEphemeralKeyPair = Util.createEphemeralKeyPair(Constants.EC_CURVE_P256);
byte[] sessionTranscript = Util.buildSessionTranscript(ephemeralKeyPair);
credential.setReaderEphemeralPublicKey(readerEphemeralKeyPair.getPublic());
credential.setSessionTranscript(sessionTranscript);
Expand Down Expand Up @@ -1101,7 +1101,7 @@ public void dynamicAuthNoUsageCountIncrement() throws Exception {
Map<String, Collection<String>> entriesToRequest = new LinkedHashMap<>();
entriesToRequest.put("org.iso.18013-5.2019", Arrays.asList("First name", "Last name"));
KeyPair ephemeralKeyPair = credential.createEphemeralKeyPair();
KeyPair readerEphemeralKeyPair = Utility.createEphemeralKeyPair(Constants.EC_CURVE_P256);
KeyPair readerEphemeralKeyPair = Util.createEphemeralKeyPair(Constants.EC_CURVE_P256);
byte[] sessionTranscript = Util.buildSessionTranscript(ephemeralKeyPair);
credential.setReaderEphemeralPublicKey(readerEphemeralKeyPair.getPublic());
credential.setSessionTranscript(sessionTranscript);
Expand All @@ -1124,7 +1124,7 @@ public void dynamicAuthNoUsageCountIncrement() throws Exception {
credential = store.getCredentialByName(credentialName,
IdentityCredentialStore.CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256);
ephemeralKeyPair = credential.createEphemeralKeyPair();
readerEphemeralKeyPair = Utility.createEphemeralKeyPair(Constants.EC_CURVE_P256);
readerEphemeralKeyPair = Util.createEphemeralKeyPair(Constants.EC_CURVE_P256);
sessionTranscript = Util.buildSessionTranscript(ephemeralKeyPair);
credential.setReaderEphemeralPublicKey(readerEphemeralKeyPair.getPublic());
credential.setSessionTranscript(sessionTranscript);
Expand All @@ -1145,7 +1145,7 @@ public void dynamicAuthNoUsageCountIncrement() throws Exception {
credential = store.getCredentialByName(credentialName,
IdentityCredentialStore.CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256);
ephemeralKeyPair = credential.createEphemeralKeyPair();
readerEphemeralKeyPair = Utility.createEphemeralKeyPair(Constants.EC_CURVE_P256);
readerEphemeralKeyPair = Util.createEphemeralKeyPair(Constants.EC_CURVE_P256);
sessionTranscript = Util.buildSessionTranscript(ephemeralKeyPair);
credential.setReaderEphemeralPublicKey(readerEphemeralKeyPair.getPublic());
credential.setSessionTranscript(sessionTranscript);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ public void multipleDocuments() throws Exception {
IdentityCredentialStore.CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256);

KeyPair ephemeralKeyPair = session.getEphemeralKeyPair();
KeyPair readerEphemeralKeyPair = Utility.createEphemeralKeyPair(Constants.EC_CURVE_P256);
KeyPair readerEphemeralKeyPair = Util.createEphemeralKeyPair(Constants.EC_CURVE_P256);
session.setReaderEphemeralPublicKey(readerEphemeralKeyPair.getPublic());
byte[] sessionTranscript = Util.buildSessionTranscript(ephemeralKeyPair);
session.setSessionTranscript(sessionTranscript);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -601,7 +601,7 @@ public void testProvisionAndRetrieveMultipleTimes() throws IdentityCredentialExc
}

KeyPair ephemeralKeyPair = credential.createEphemeralKeyPair();
KeyPair readerEphemeralKeyPair = Utility.createEphemeralKeyPair(Constants.EC_CURVE_P256);
KeyPair readerEphemeralKeyPair = Util.createEphemeralKeyPair(Constants.EC_CURVE_P256);
credential.setReaderEphemeralPublicKey(readerEphemeralKeyPair.getPublic());
byte[] sessionTranscript = Util.buildSessionTranscript(ephemeralKeyPair);

Expand All @@ -621,7 +621,7 @@ public void testProvisionAndRetrieveMultipleTimes() throws IdentityCredentialExc

// Now try with a different (but still valid) sessionTranscript - this should fail with
// a RuntimeException
KeyPair otherEphemeralKeyPair = Utility.createEphemeralKeyPair(Constants.EC_CURVE_P256);
KeyPair otherEphemeralKeyPair = Util.createEphemeralKeyPair(Constants.EC_CURVE_P256);
byte[] otherSessionTranscript = Util.buildSessionTranscript(otherEphemeralKeyPair);
try {
credential.setSessionTranscript(otherSessionTranscript);
Expand Down
Loading

0 comments on commit 982ad4b

Please sign in to comment.