Repo Created

This commit is contained in:
Fr4nz D13trich 2025-11-15 17:44:12 +01:00
parent eb305e2886
commit a8c22c65db
4784 changed files with 329907 additions and 2 deletions

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ SPDX-FileCopyrightText: 2022 microG Project Team
~ SPDX-License-Identifier: Apache-2.0
-->
<manifest />

View file

@ -0,0 +1,8 @@
package com.google.android.gms.fido.fido2.api;
import com.google.android.gms.common.api.Status;
interface IBooleanCallback {
void onBoolean(boolean value) = 0;
void onError(in Status status) = 1;
}

View file

@ -0,0 +1,9 @@
package com.google.android.gms.fido.fido2.api;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.fido.fido2.api.common.FidoCredentialDetails;
interface ICredentialListCallback {
void onCredentialList(in List<FidoCredentialDetails> value) = 0;
void onError(in Status status) = 1;
}

View file

@ -0,0 +1,3 @@
package com.google.android.gms.fido.fido2.api.common;
parcelable BrowserPublicKeyCredentialCreationOptions;

View file

@ -0,0 +1,3 @@
package com.google.android.gms.fido.fido2.api.common;
parcelable BrowserPublicKeyCredentialRequestOptions;

View file

@ -0,0 +1,3 @@
package com.google.android.gms.fido.fido2.api.common;
parcelable FidoCredentialDetails;

View file

@ -0,0 +1,3 @@
package com.google.android.gms.fido.fido2.api.common;
parcelable PublicKeyCredentialCreationOptions;

View file

@ -0,0 +1,3 @@
package com.google.android.gms.fido.fido2.api.common;
parcelable PublicKeyCredentialRequestOptions;

View file

@ -0,0 +1,8 @@
package com.google.android.gms.fido.fido2.internal.privileged;
import android.app.PendingIntent;
import com.google.android.gms.common.api.Status;
interface IFido2PrivilegedCallbacks {
void onPendingIntent(in Status status, in PendingIntent pendingIntent);
}

View file

@ -0,0 +1,14 @@
package com.google.android.gms.fido.fido2.internal.privileged;
import com.google.android.gms.fido.fido2.internal.privileged.IFido2PrivilegedCallbacks;
import com.google.android.gms.fido.fido2.api.IBooleanCallback;
import com.google.android.gms.fido.fido2.api.ICredentialListCallback;
import com.google.android.gms.fido.fido2.api.common.BrowserPublicKeyCredentialCreationOptions;
import com.google.android.gms.fido.fido2.api.common.BrowserPublicKeyCredentialRequestOptions;
interface IFido2PrivilegedService {
void getRegisterPendingIntent(IFido2PrivilegedCallbacks callbacks, in BrowserPublicKeyCredentialCreationOptions options) = 0;
void getSignPendingIntent(IFido2PrivilegedCallbacks callbacks, in BrowserPublicKeyCredentialRequestOptions options) = 1;
void isUserVerifyingPlatformAuthenticatorAvailable(IBooleanCallback callbacks) = 2;
void getCredentialList(ICredentialListCallback callbacks, String rpId) = 3;
}

View file

@ -0,0 +1,8 @@
package com.google.android.gms.fido.fido2.internal.regular;
import android.app.PendingIntent;
import com.google.android.gms.common.api.Status;
interface IFido2AppCallbacks {
void onPendingIntent(in Status status, in PendingIntent pendingIntent);
}

View file

@ -0,0 +1,13 @@
package com.google.android.gms.fido.fido2.internal.regular;
import com.google.android.gms.fido.fido2.internal.regular.IFido2AppCallbacks;
import com.google.android.gms.fido.fido2.api.IBooleanCallback;
import com.google.android.gms.fido.fido2.api.ICredentialListCallback;
import com.google.android.gms.fido.fido2.api.common.PublicKeyCredentialCreationOptions;
import com.google.android.gms.fido.fido2.api.common.PublicKeyCredentialRequestOptions;
interface IFido2AppService {
void getRegisterPendingIntent(IFido2AppCallbacks callbacks, in PublicKeyCredentialCreationOptions options) = 0;
void getSignPendingIntent(IFido2AppCallbacks callbacks, in PublicKeyCredentialRequestOptions options) = 1;
void isUserVerifyingPlatformAuthenticatorAvailable(IBooleanCallback callbacks) = 2;
}

View file

@ -0,0 +1,122 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.fido;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import com.google.android.gms.fido.fido2.api.common.AuthenticatorAssertionResponse;
import com.google.android.gms.fido.fido2.api.common.AuthenticatorAttestationResponse;
import com.google.android.gms.fido.fido2.api.common.AuthenticatorErrorResponse;
import com.google.android.gms.fido.fido2.api.common.PublicKeyCredential;
import com.google.android.gms.fido.fido2.Fido2ApiClient;
import com.google.android.gms.fido.fido2.Fido2PendingIntent;
import com.google.android.gms.fido.fido2.Fido2PrivilegedApiClient;
import com.google.android.gms.fido.sourcedevice.SourceDirectTransferClient;
import com.google.android.gms.fido.u2f.U2fApiClient;
import org.microg.gms.common.PublicApi;
/**
* Entry point for Fido APIs.
* <p>
* FIDO (Fast IDentity Online), which is the industry alliance where Security Keys are being standardized.
*/
@PublicApi
public class Fido {
/**
* The key used by the calling {@link Activity} to retrieve {@link PublicKeyCredential} from the Intent received by
* {@link Activity#onActivityResult(int, int, Intent)} after launching {@link Fido2PendingIntent}.
*/
public static final String FIDO2_KEY_CREDENTIAL_EXTRA = "FIDO2_CREDENTIAL_EXTRA";
/**
* The key used by the calling {@link Activity} to retrieve {@link AuthenticatorErrorResponse} from the Intent received by
* {@link Activity#onActivityResult(int, int, Intent)} after launching {@link Fido2PendingIntent}.
*
* @deprecated use {@link #FIDO2_KEY_CREDENTIAL_EXTRA} to fetch {@link PublicKeyCredential} instead.
* {@link PublicKeyCredential} contains an {@link AuthenticatorErrorResponse}.
*/
@Deprecated
public static final String FIDO2_KEY_ERROR_EXTRA = "FIDO2_ERROR_EXTRA";
/**
* The key used by the calling {@link Activity} to retrieve {@link AuthenticatorAttestationResponse} or
* {@link AuthenticatorAssertionResponse} from the Intent received by
* {@link Activity#onActivityResult(int, int, Intent)} after launching {@link Fido2PendingIntent}.
*
* @deprecated use {@link #FIDO2_KEY_CREDENTIAL_EXTRA} to fetch {@link PublicKeyCredential} instead.
* {@link PublicKeyCredential} contains an {@link AuthenticatorAttestationResponse} or an {@link AuthenticatorAssertionResponse}.
*/
@Deprecated
public static final String FIDO2_KEY_RESPONSE_EXTRA = "FIDO2_RESPONSE_EXTRA";
/**
* The key used by the calling {@link Activity} to retrieve {@link ResponseData} from the Intent received by
* {@link Activity#onActivityResult(int, int, Intent)} after launching {@link Fido2PendingIntent}.
*/
public static final String KEY_RESPONSE_EXTRA = "RESPONSE_EXTRA";
/**
* Creates a new instance of {@link Fido2ApiClient} for use in a non-activity {@link Context}.
*/
public static Fido2ApiClient getFido2ApiClient(Context context) {
return new Fido2ApiClient(context);
}
/**
* Creates a new instance of {@link Fido2ApiClient} for use in an {@link Activity}.
*/
public static Fido2ApiClient getFido2ApiClient(Activity activity) {
return new Fido2ApiClient(activity);
}
/**
* Creates a new instance of {@link Fido2PrivilegedApiClient} for use in a non-activity {@link Context}.
*/
public static Fido2PrivilegedApiClient getFido2PrivilegedApiClient(Context context) {
return new Fido2PrivilegedApiClient(context);
}
/**
* Creates a new instance of {@link Fido2PrivilegedApiClient} for use in an {@link Activity}.
*/
public static Fido2PrivilegedApiClient getFido2PrivilegedApiClient(Activity activity) {
return new Fido2PrivilegedApiClient(activity);
}
/**
* Creates a new instance of {@link SourceDirectTransferClient} for use in a non-activity {@link Context}.
*/
public static final SourceDirectTransferClient getSourceDirectTransferClient(Context context) {
throw new UnsupportedOperationException();
}
/**
* Creates a new instance of {@link SourceDirectTransferClient} for use in an {@link Activity}.
*/
public static final SourceDirectTransferClient getSourceDirectTransferClient(Activity activity) {
throw new UnsupportedOperationException();
}
/**
* Creates a new instance of {@link U2fApiClient} for use in a non-activity {@link Context}.
*/
public static U2fApiClient getU2fApiClient(Context context) {
return new U2fApiClient(context);
}
/**
* Creates a new instance of {@link U2fApiClient} for use in an {@link Activity}.
*/
public static U2fApiClient getU2fApiClient(Activity activity) {
return new U2fApiClient(activity);
}
}

View file

@ -0,0 +1,109 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.fido.common;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
import org.json.JSONArray;
import org.json.JSONException;
import org.microg.gms.common.PublicApi;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* The transport between the authenticator and the client.
*/
@PublicApi
public enum Transport implements Parcelable {
BLUETOOTH_CLASSIC("bt"),
BLUETOOTH_LOW_ENERGY("ble"),
NFC("nfc"),
USB("usb"),
INTERNAL("internal"),
HYBRID("cable");
private final String value;
Transport(String value) {
this.value = value;
}
@Override
public String toString() {
return value;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(toString());
}
@PublicApi(exclude = true)
public static Transport fromString(String transport) throws UnsupportedTransportException {
for (Transport value : values()) {
if (value.value.equals(transport)) return value;
}
if (transport.equals("hybrid")) {
return HYBRID;
}
throw new UnsupportedTransportException("Transport " + transport + " not supported");
}
@PublicApi(exclude = true)
public static List<Transport> parseTransports(JSONArray jsonArray) throws JSONException {
if (jsonArray == null) return null;
Set<Transport> set = new HashSet<>();
for (int i = 0; i < jsonArray.length(); i++) {
String transport = jsonArray.getString(i);
if (transport != null && !transport.isEmpty()) {
try {
set.add(fromString(transport));
} catch (UnsupportedTransportException e) {
Log.w("Transport", "Ignoring unrecognized transport " + transport);
}
}
}
return new ArrayList<>(set);
}
public static Creator<Transport> CREATOR = new Creator<Transport>() {
@Override
public Transport createFromParcel(Parcel source) {
try {
return Transport.fromString(source.readString());
} catch (UnsupportedTransportException e) {
throw new RuntimeException(e);
}
}
@Override
public Transport[] newArray(int size) {
return new Transport[size];
}
};
/**
* Exception thrown when an unsupported or unrecognized transport is encountered.
*/
public static class UnsupportedTransportException extends Exception {
public UnsupportedTransportException(String errorMessage) {
super(errorMessage);
}
}
}

View file

@ -0,0 +1,134 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.fido.fido2;
import android.app.PendingIntent;
import android.content.Context;
import android.os.RemoteException;
import com.google.android.gms.common.api.Api;
import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.common.api.GoogleApi;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.fido.fido2.api.IBooleanCallback;
import com.google.android.gms.fido.fido2.api.common.PublicKeyCredentialCreationOptions;
import com.google.android.gms.fido.fido2.api.common.PublicKeyCredentialRequestOptions;
import com.google.android.gms.fido.fido2.internal.regular.IFido2AppCallbacks;
import com.google.android.gms.tasks.Task;
import com.google.android.gms.tasks.Tasks;
import org.microg.gms.common.PublicApi;
import org.microg.gms.common.api.PendingGoogleApiCall;
import org.microg.gms.fido.fido2.Fido2GmsClient;
import org.microg.gms.fido.fido2.Fido2PendingIntentImpl;
/**
* The entry point for interacting with FIDO2 APIs.
*/
@PublicApi
public class Fido2ApiClient extends GoogleApi<Api.ApiOptions.NoOptions> {
private static final Api<Api.ApiOptions.NoOptions> API = new Api<>((options, context, looper, clientSettings, callbacks, connectionFailedListener) -> new Fido2GmsClient(context, callbacks, connectionFailedListener));
@PublicApi(exclude = true)
public Fido2ApiClient(Context context) {
super(context, API, Api.ApiOptions.NO_OPTIONS);
}
/**
* @deprecated use {@link #getRegisterPendingIntent(PublicKeyCredentialCreationOptions)} instead
*/
@Deprecated
public Task<Fido2PendingIntent> getRegisterIntent(PublicKeyCredentialCreationOptions requestOptions) {
return getRegisterPendingIntent(requestOptions).onSuccessTask(pendingIntent -> Tasks.forResult(new Fido2PendingIntentImpl(pendingIntent)));
}
/**
* Creates a Task with {@link PendingIntent}, when started, will issue a FIDO2 registration request, which is done
* once per FIDO2 device per account for associating the new FIDO2 device with that account.
*
* @param requestOptions for the registration request
* @return Task with PendingIntent to launch FIDO2 registration request
*/
public Task<PendingIntent> getRegisterPendingIntent(PublicKeyCredentialCreationOptions requestOptions) {
return scheduleTask((PendingGoogleApiCall<PendingIntent, Fido2GmsClient>) (client, completionSource) -> {
try {
client.getRegisterPendingIntent(new IFido2AppCallbacks.Stub() {
@Override
public void onPendingIntent(Status status, PendingIntent pendingIntent) throws RemoteException {
if (status.isSuccess()) {
completionSource.setResult(pendingIntent);
} else {
completionSource.setException(new ApiException(status));
}
}
}, requestOptions);
} catch (Exception e) {
completionSource.setException(e);
}
});
}
/**
* @deprecated use {@link #getSignPendingIntent(PublicKeyCredentialRequestOptions)} instead
*/
@Deprecated
public Task<Fido2PendingIntent> getSignIntent(PublicKeyCredentialRequestOptions requestOptions) {
return getSignPendingIntent(requestOptions).onSuccessTask(pendingIntent -> Tasks.forResult(new Fido2PendingIntentImpl(pendingIntent)));
}
/**
* Creates a Task with {@link PendingIntent}, when started, will issue a FIDO2 signature request for a relying
* party to authenticate a user.
*
* @param requestOptions for the sign request
* @return Task with PendingIntent to launch FIDO2 signature request
*/
public Task<PendingIntent> getSignPendingIntent(PublicKeyCredentialRequestOptions requestOptions) {
return scheduleTask((PendingGoogleApiCall<PendingIntent, Fido2GmsClient>) (client, completionSource) -> {
try {
client.getSignPendingIntent(new IFido2AppCallbacks.Stub() {
@Override
public void onPendingIntent(Status status, PendingIntent pendingIntent) throws RemoteException {
if (status.isSuccess()) {
completionSource.setResult(pendingIntent);
} else {
completionSource.setException(new ApiException(status));
}
}
}, requestOptions);
} catch (Exception e) {
completionSource.setException(e);
}
});
}
/**
* Creates a Task with {@link Boolean}, which check if a user verifying platform authenticator is available on the
* device.
*/
public Task<Boolean> isUserVerifyingPlatformAuthenticatorAvailable() {
return scheduleTask((PendingGoogleApiCall<Boolean, Fido2GmsClient>) (client, completionSource) -> {
try {
client.isUserVerifyingPlatformAuthenticatorAvailable(new IBooleanCallback.Stub() {
@Override
public void onBoolean(boolean value) throws RemoteException {
completionSource.setResult(value);
}
@Override
public void onError(Status status) throws RemoteException {
completionSource.setException(new ApiException(status));
}
});
} catch (Exception e) {
completionSource.setException(e);
}
});
}
}

View file

@ -0,0 +1,37 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.fido.fido2;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.IntentSender;
/**
* Use {@link Fido2ApiClient#getRegisterPendingIntent(PublicKeyCredentialCreationOptions)} or
* {@link Fido2ApiClient#getSignPendingIntent(PublicKeyCredentialRequestOptions)} to avoid a dependence on this.
*/
@Deprecated
public interface Fido2PendingIntent {
/**
* Returns true if an {@link Activity} has a {@link PendingIntent}.
*/
boolean hasPendingIntent();
/**
* Launches the PendingIntent.
*
* @param activity An Activity context to use to launch the intent. The activity's onActivityResult method will
* be invoked after the user is done.
* @param requestCode The request code to pass to onActivityResult.
* @throws IllegalStateException if hasPendingIntent is false
* @throws IntentSender.SendIntentException If the resolution intent has been canceled or is no longer able to
* execute the request.
*/
void launchPendingIntent(Activity activity, int requestCode) throws IntentSender.SendIntentException;
}

View file

@ -0,0 +1,171 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.fido.fido2;
import android.app.PendingIntent;
import android.content.Context;
import android.os.RemoteException;
import com.google.android.gms.common.api.Api;
import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.common.api.GoogleApi;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.fido.fido2.api.IBooleanCallback;
import com.google.android.gms.fido.fido2.api.ICredentialListCallback;
import com.google.android.gms.fido.fido2.api.common.BrowserPublicKeyCredentialCreationOptions;
import com.google.android.gms.fido.fido2.api.common.BrowserPublicKeyCredentialRequestOptions;
import com.google.android.gms.fido.fido2.api.common.FidoCredentialDetails;
import com.google.android.gms.fido.fido2.internal.privileged.IFido2PrivilegedCallbacks;
import com.google.android.gms.tasks.Task;
import com.google.android.gms.tasks.Tasks;
import org.microg.gms.common.PublicApi;
import org.microg.gms.common.api.PendingGoogleApiCall;
import org.microg.gms.fido.fido2.Fido2PendingIntentImpl;
import org.microg.gms.fido.fido2.Fido2PrivilegedGmsClient;
import java.util.List;
/**
* The entry point for interacting with the privileged FIDO2 APIs.
*/
@PublicApi
public class Fido2PrivilegedApiClient extends GoogleApi<Api.ApiOptions.NoOptions> {
private static final Api<Api.ApiOptions.NoOptions> API = new Api<>((options, context, looper, clientSettings, callbacks, connectionFailedListener) -> new Fido2PrivilegedGmsClient(context, callbacks, connectionFailedListener));
@PublicApi(exclude = true)
public Fido2PrivilegedApiClient(Context context) {
super(context, API, Api.ApiOptions.NO_OPTIONS);
}
/**
* Creates a Task with a list of {@link FidoCredentialDetails} which, when started, will retrieve a list of credentials associated
* with the given relying party ID.
*
* @param rpId indicating the relying party for which we want to list credentials
* @return PendingResult with PendingIntent to retrieve the credential list
*/
public Task<List<FidoCredentialDetails>> getCredentialList(String rpId) {
return scheduleTask((PendingGoogleApiCall<List<FidoCredentialDetails>, Fido2PrivilegedGmsClient>) (client, completionSource) -> {
try {
client.getCredentialList(new ICredentialListCallback.Stub() {
@Override
public void onCredentialList(List<FidoCredentialDetails> value) throws RemoteException {
completionSource.setResult(value);
}
@Override
public void onError(Status status) throws RemoteException {
completionSource.setException(new ApiException(status));
}
}, rpId);
} catch (Exception e) {
completionSource.setException(e);
}
});
}
/**
* Creates a Task with PendingIntent, when started, will issue a FIDO2 registration request for privileged apps.
*
* @param requestOptions for the registration request from a Web browser
* @return PendingResult with PendingIntent to launch FIDO2 registration request
* @deprecated use {@link #getRegisterPendingIntent(BrowserPublicKeyCredentialCreationOptions)} instead
*/
@Deprecated
public Task<Fido2PendingIntent> getRegisterIntent(BrowserPublicKeyCredentialCreationOptions requestOptions) {
return getRegisterPendingIntent(requestOptions).onSuccessTask(pendingIntent -> Tasks.forResult(new Fido2PendingIntentImpl(pendingIntent)));
}
/**
* Creates a Task with PendingIntent, when started, will issue a FIDO2 registration request for privileged apps.
*
* @param requestOptions for the registration request from a Web browser
* @return PendingResult with PendingIntent to launch FIDO2 registration request
*/
public Task<PendingIntent> getRegisterPendingIntent(BrowserPublicKeyCredentialCreationOptions requestOptions) {
return scheduleTask((PendingGoogleApiCall<PendingIntent, Fido2PrivilegedGmsClient>) (client, completionSource) -> {
try {
client.getRegisterPendingIntent(new IFido2PrivilegedCallbacks.Stub() {
@Override
public void onPendingIntent(Status status, PendingIntent pendingIntent) throws RemoteException {
if (status.isSuccess()) {
completionSource.setResult(pendingIntent);
} else {
completionSource.setException(new ApiException(status));
}
}
}, requestOptions);
} catch (Exception e) {
completionSource.setException(e);
}
});
}
/**
* Creates a Task with PendingIntent, when started, will issue a FIDO2 signature request for privileged apps.
*
* @param requestOptions for the sign request from a Web browser
* @return PendingResult with PendingIntent to launch FIDO2 signature request
* @deprecated use {@link #getSignPendingIntent(BrowserPublicKeyCredentialRequestOptions)} instead
*/
@Deprecated
public Task<Fido2PendingIntent> getSignIntent(BrowserPublicKeyCredentialRequestOptions requestOptions) {
return getSignPendingIntent(requestOptions).onSuccessTask(pendingIntent -> Tasks.forResult(new Fido2PendingIntentImpl(pendingIntent)));
}
/**
* Creates a Task with PendingIntent, when started, will issue a FIDO2 signature request for privileged apps.
*
* @param requestOptions for the sign request from a Web browser
* @return PendingResult with PendingIntent to launch FIDO2 signature request
*/
public Task<PendingIntent> getSignPendingIntent(BrowserPublicKeyCredentialRequestOptions requestOptions) {
return scheduleTask((PendingGoogleApiCall<PendingIntent, Fido2PrivilegedGmsClient>) (client, completionSource) -> {
try {
client.getSignPendingIntent(new IFido2PrivilegedCallbacks.Stub() {
@Override
public void onPendingIntent(Status status, PendingIntent pendingIntent) throws RemoteException {
if (status.isSuccess()) {
completionSource.setResult(pendingIntent);
} else {
completionSource.setException(new ApiException(status));
}
}
}, requestOptions);
} catch (Exception e) {
completionSource.setException(e);
}
});
}
/**
* Creates a Task with {@link Boolean}, which check if a user verifying platform authenticator is available on the
* device.
*/
public Task<Boolean> isUserVerifyingPlatformAuthenticatorAvailable() {
return scheduleTask((PendingGoogleApiCall<Boolean, Fido2PrivilegedGmsClient>) (client, completionSource) -> {
try {
client.isUserVerifyingPlatformAuthenticatorAvailable(new IBooleanCallback.Stub() {
@Override
public void onBoolean(boolean value) throws RemoteException {
completionSource.setResult(value);
}
@Override
public void onError(Status status) throws RemoteException {
completionSource.setException(new ApiException(status));
}
});
} catch (Exception e) {
completionSource.setException(e);
}
});
}
}

View file

@ -0,0 +1,20 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.fido.fido2.api.common;
/**
* An interface for an algorithm used in public key encryption. All implementations must conform to the guidelines
* regarding algorithm registrations in RFC8152.
*/
public interface Algorithm {
/**
* Gets the COSE value for the algorithm used in the encryption of the credential.
*/
int getAlgoValue();
}

View file

@ -0,0 +1,75 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.google.android.gms.fido.fido2.api.common;
import android.os.Parcel;
import android.os.Parcelable;
import org.microg.gms.common.Hide;
/**
* Clients may communicate with authenticators using a variety of mechanisms. We define authenticators that are
* part of the client's platform as having a platform attachment, and refer to them as platform authenticators.
* While those that are reachable via cross-platform transport protocols are defined as having cross-platform
* attachment, and refer to them as roaming authenticators.
*/
public enum Attachment implements Parcelable {
PLATFORM("platform"),
CROSS_PLATFORM("cross-platform");
private final String value;
Attachment(String value) {
this.value = value;
}
@Override
public String toString() {
return value;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(toString());
}
@Hide
public static Attachment fromString(String attachment) throws UnsupportedAttachmentException {
for (Attachment value : values()) {
if (value.value.equals(attachment)) return value;
}
throw new UnsupportedAttachmentException("Attachment " + attachment + " not supported");
}
public static Creator<Attachment> CREATOR = new Creator<Attachment>() {
@Override
public Attachment createFromParcel(Parcel source) {
try {
return Attachment.fromString(source.readString());
} catch (Attachment.UnsupportedAttachmentException e) {
throw new RuntimeException(e);
}
}
@Override
public Attachment[] newArray(int size) {
return new Attachment[size];
}
};
/**
* Exception thrown when an unsupported or unrecognized attachment is encountered.
*/
public static class UnsupportedAttachmentException extends Exception {
public UnsupportedAttachmentException(String message) {
super(message);
}
}
}

View file

@ -0,0 +1,79 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.fido.fido2.api.common;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.NonNull;
import org.microg.gms.common.Hide;
/**
* An enum describing the relying party's preference for attestation conveyance.
*/
public enum AttestationConveyancePreference implements Parcelable {
NONE("none"),
INDIRECT("indirect"),
DIRECT("direct");
private final String value;
AttestationConveyancePreference(String value) {
this.value = value;
}
@Override
@NonNull
public String toString() {
return value;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(toString());
}
@Hide
@NonNull
public static AttestationConveyancePreference fromString(String attachment) throws UnsupportedAttestationConveyancePreferenceException {
for (AttestationConveyancePreference value : values()) {
if (value.value.equals(attachment)) return value;
}
throw new UnsupportedAttestationConveyancePreferenceException("Attestation conveyance preference " + attachment + " not supported");
}
public static Creator<AttestationConveyancePreference> CREATOR = new Creator<AttestationConveyancePreference>() {
@Override
public AttestationConveyancePreference createFromParcel(Parcel source) {
try {
return AttestationConveyancePreference.fromString(source.readString());
} catch (UnsupportedAttestationConveyancePreferenceException e) {
throw new RuntimeException(e);
}
}
@Override
public AttestationConveyancePreference[] newArray(int size) {
return new AttestationConveyancePreference[size];
}
};
/**
* Exception thrown when an unsupported or unrecognized attestation conveyance preference is encountered.
*/
public static class UnsupportedAttestationConveyancePreferenceException extends Exception {
public UnsupportedAttestationConveyancePreferenceException(String message) {
super(message);
}
}
}

View file

@ -0,0 +1,240 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.fido.fido2.api.common;
import android.os.Parcel;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import org.microg.gms.common.Hide;
import org.microg.gms.common.PublicApi;
import org.microg.gms.utils.ToStringHelper;
import java.util.Arrays;
import java.util.Objects;
/**
* Represents extensions that can be passed into FIDO2 APIs. This container class corresponds to the additional
* parameters requesting additional processing by authenticators.
* <p>
* Note that rather than accepting arbitrary objects as specified in WebAuthn, this class requires a structured entry
* for each supported extension.
*/
@PublicApi
@SafeParcelable.Class
public class AuthenticationExtensions extends AbstractSafeParcelable {
@Field(value = 2, getterName = "getFidoAppIdExtension")
@Nullable
private FidoAppIdExtension fidoAppIdExtension;
@Field(value = 3, getterName = "getCableAuthenticationExtension")
@Nullable
private CableAuthenticationExtension cableAuthenticationExtension;
@Field(value = 4, getterName = "getUserVerificationMethodExtension")
@Nullable
private UserVerificationMethodExtension userVerificationMethodExtension;
@Field(value = 5, getterName = "getGoogleMultiAssertionExtension")
@Nullable
private GoogleMultiAssertionExtension googleMultiAssertionExtension;
@Field(value = 6, getterName = "getGoogleSessionIdExtension")
@Nullable
private GoogleSessionIdExtension googleSessionIdExtension;
@Field(value = 7, getterName = "getGoogleSilentVerificationExtension")
@Nullable
private GoogleSilentVerificationExtension googleSilentVerificationExtension;
@Field(value = 8, getterName = "getDevicePublicKeyExtension")
@Nullable
private DevicePublicKeyExtension devicePublicKeyExtension;
@Field(value = 9, getterName = "getGoogleTunnelServerIdExtension")
@Nullable
private GoogleTunnelServerIdExtension googleTunnelServerIdExtension;
@Field(value = 10, getterName = "getGoogleThirdPartyPaymentExtension")
@Nullable
private GoogleThirdPartyPaymentExtension googleThirdPartyPaymentExtension;
@Field(value = 11, getterName = "getPrfExtension")
@Nullable
private PrfExtension prfExtension;
@Field(value = 12, getterName = "getSimpleTransactionAuthorizationExtension")
@Nullable
private SimpleTransactionAuthorizationExtension simpleTransactionAuthorizationExtension;
@Field(value = 13, getterName = "getHmacSecretExtension")
@Nullable
private HmacSecretExtension hmacSecretExtension;
@Field(value = 14, getterName = "getPaymentExtension")
@Nullable
private PaymentExtension paymentExtension;
@Constructor
public AuthenticationExtensions(@Param(2) @Nullable FidoAppIdExtension fidoAppIdExtension, @Param(3) @Nullable CableAuthenticationExtension cableAuthenticationExtension, @Param(4) @Nullable UserVerificationMethodExtension userVerificationMethodExtension, @Param(5) @Nullable GoogleMultiAssertionExtension googleMultiAssertionExtension, @Param(6) @Nullable GoogleSessionIdExtension googleSessionIdExtension, @Param(7) @Nullable GoogleSilentVerificationExtension googleSilentVerificationExtension, @Param(8) @Nullable DevicePublicKeyExtension devicePublicKeyExtension, @Param(9) @Nullable GoogleTunnelServerIdExtension googleTunnelServerIdExtension, @Param(10) @Nullable GoogleThirdPartyPaymentExtension googleThirdPartyPaymentExtension, @Param(11) @Nullable PrfExtension prfExtension, @Param(12) @Nullable SimpleTransactionAuthorizationExtension simpleTransactionAuthorizationExtension, @Param(13) @Nullable HmacSecretExtension hmacSecretExtension, @Param(14) @Nullable PaymentExtension paymentExtension) {
this.fidoAppIdExtension = fidoAppIdExtension;
this.cableAuthenticationExtension = cableAuthenticationExtension;
this.userVerificationMethodExtension = userVerificationMethodExtension;
this.googleMultiAssertionExtension = googleMultiAssertionExtension;
this.googleSessionIdExtension = googleSessionIdExtension;
this.googleSilentVerificationExtension = googleSilentVerificationExtension;
this.devicePublicKeyExtension = devicePublicKeyExtension;
this.googleTunnelServerIdExtension = googleTunnelServerIdExtension;
this.googleThirdPartyPaymentExtension = googleThirdPartyPaymentExtension;
this.prfExtension = prfExtension;
this.simpleTransactionAuthorizationExtension = simpleTransactionAuthorizationExtension;
this.hmacSecretExtension = hmacSecretExtension;
this.paymentExtension = paymentExtension;
}
@Nullable
public FidoAppIdExtension getFidoAppIdExtension() {
return fidoAppIdExtension;
}
@Hide
@Nullable
public CableAuthenticationExtension getCableAuthenticationExtension() {
return cableAuthenticationExtension;
}
@Nullable
public UserVerificationMethodExtension getUserVerificationMethodExtension() {
return userVerificationMethodExtension;
}
@Nullable
public GoogleMultiAssertionExtension getGoogleMultiAssertionExtension() {
return googleMultiAssertionExtension;
}
@Nullable
public GoogleSessionIdExtension getGoogleSessionIdExtension() {
return googleSessionIdExtension;
}
@Nullable
public GoogleSilentVerificationExtension getGoogleSilentVerificationExtension() {
return googleSilentVerificationExtension;
}
@Nullable
public DevicePublicKeyExtension getDevicePublicKeyExtension() {
return devicePublicKeyExtension;
}
@Nullable
public GoogleTunnelServerIdExtension getGoogleTunnelServerIdExtension() {
return googleTunnelServerIdExtension;
}
@Nullable
public GoogleThirdPartyPaymentExtension getGoogleThirdPartyPaymentExtension() {
return googleThirdPartyPaymentExtension;
}
@Nullable
public PrfExtension getPrfExtension() {
return prfExtension;
}
@Nullable
public SimpleTransactionAuthorizationExtension getSimpleTransactionAuthorizationExtension() {
return simpleTransactionAuthorizationExtension;
}
@Nullable
public HmacSecretExtension getHmacSecretExtension() {
return hmacSecretExtension;
}
@Nullable
public PaymentExtension getPaymentExtension() {
return paymentExtension;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof AuthenticationExtensions)) return false;
AuthenticationExtensions that = (AuthenticationExtensions) o;
if (!Objects.equals(fidoAppIdExtension, that.fidoAppIdExtension)) return false;
if (!Objects.equals(cableAuthenticationExtension, that.cableAuthenticationExtension)) return false;
if (!Objects.equals(userVerificationMethodExtension, that.userVerificationMethodExtension)) return false;
if (!Objects.equals(googleMultiAssertionExtension, that.googleMultiAssertionExtension)) return false;
if (!Objects.equals(googleSessionIdExtension, that.googleSessionIdExtension)) return false;
if (!Objects.equals(googleSilentVerificationExtension, that.googleSilentVerificationExtension)) return false;
if (!Objects.equals(devicePublicKeyExtension, that.devicePublicKeyExtension)) return false;
if (!Objects.equals(googleTunnelServerIdExtension, that.googleTunnelServerIdExtension)) return false;
if (!Objects.equals(googleThirdPartyPaymentExtension, that.googleThirdPartyPaymentExtension)) return false;
if (!Objects.equals(prfExtension, that.prfExtension)) return false;
if (!Objects.equals(simpleTransactionAuthorizationExtension, that.simpleTransactionAuthorizationExtension)) return false;
if (!Objects.equals(hmacSecretExtension, that.hmacSecretExtension)) return false;
return Objects.equals(paymentExtension, that.paymentExtension);
}
@Override
public int hashCode() {
return Arrays.hashCode(new Object[]{fidoAppIdExtension, cableAuthenticationExtension, userVerificationMethodExtension, googleMultiAssertionExtension, googleSessionIdExtension, googleSilentVerificationExtension, devicePublicKeyExtension, googleTunnelServerIdExtension, googleThirdPartyPaymentExtension, prfExtension, simpleTransactionAuthorizationExtension, hmacSecretExtension, paymentExtension});
}
@Override
public String toString() {
return ToStringHelper.name("AuthenticationExtensions").field("fidoAppIdExtension", fidoAppIdExtension != null ? fidoAppIdExtension.getAppId() : null).field("cableAuthenticationExtension", cableAuthenticationExtension).field("userVerificationMethodExtension", userVerificationMethodExtension != null ? userVerificationMethodExtension.getUvm() : null).field("googleMultiAssertionExtension", googleMultiAssertionExtension).field("googleSessionIdExtension", googleSessionIdExtension).field("googleSilentVerificationExtension", googleSilentVerificationExtension).field("devicePublicKeyExtension", devicePublicKeyExtension).field("googleTunnelServerIdExtension", googleTunnelServerIdExtension).field("googleThirdPartyPaymentExtension", googleThirdPartyPaymentExtension).field("prfExtension", prfExtension).field("simpleTransactionAuthorizationExtension", simpleTransactionAuthorizationExtension).field("hmacSecretExtension", hmacSecretExtension).field("paymentExtension", paymentExtension).end();
}
/**
* Builder for {@link AuthenticationExtensions}.
*/
public static class Builder {
@Nullable
private FidoAppIdExtension fidoAppIdExtension;
@Nullable
private UserVerificationMethodExtension userVerificationMethodExtension;
/**
* The constructor of {@link AuthenticationExtensions.Builder}.
*/
public Builder() {
}
/**
* Sets the App ID extension, which allows for authentication of U2F authenticators previously registered
* under the supplied App ID.
*/
public Builder setFido2Extension(@Nullable FidoAppIdExtension appIdExtension) {
this.fidoAppIdExtension = appIdExtension;
return this;
}
/**
* Sets the User Verification Method extension, which allows the relying party to ascertain up to three
* authentication methods that were used.
*/
public Builder setUserVerificationMethodExtension(@Nullable UserVerificationMethodExtension userVerificationMethodExtension) {
this.userVerificationMethodExtension = userVerificationMethodExtension;
return this;
}
/**
* Builds the {@link AuthenticationExtensions} object.
*/
@NonNull
public AuthenticationExtensions build() {
return new AuthenticationExtensions(fidoAppIdExtension, null, userVerificationMethodExtension, null, null, null, null, null, null, null, null, null, null);
}
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
CREATOR.writeToParcel(this, dest, flags);
}
public static final SafeParcelableCreatorAndWriter<AuthenticationExtensions> CREATOR = findCreator(AuthenticationExtensions.class);
}

View file

@ -0,0 +1,195 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.fido.fido2.api.common;
import android.os.Parcel;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableSerializer;
import org.microg.gms.common.PublicApi;
import java.util.Arrays;
import java.util.Objects;
/**
* This container class represents client output for extensions that can be passed into FIDO2 APIs.
*/
@PublicApi
@SafeParcelable.Class
public class AuthenticationExtensionsClientOutputs extends AbstractSafeParcelable {
@Field(value = 1, getterName = "getUvmEntries")
@Nullable
private UvmEntries uvmEntries;
@Field(value = 2, getterName = "getDevicePublicKeyOutputs")
@Nullable
private AuthenticationExtensionsDevicePublicKeyOutputs devicePublicKeyOutputs;
@Field(value = 3, getterName = "getCredProps")
@Nullable
private AuthenticationExtensionsCredPropsOutputs credProps;
@Field(value = 4, getterName = "getPrfOutputs")
@Nullable
private AuthenticationExtensionsPrfOutputs prfOutputs;
@Field(value = 5, getterName = "getTxAuthSimple")
@Nullable
private String txAuthSimple;
@Constructor
public AuthenticationExtensionsClientOutputs(@Param(1) @Nullable UvmEntries uvmEntries, @Param(2) @Nullable AuthenticationExtensionsDevicePublicKeyOutputs devicePublicKeyOutputs, @Param(3) @Nullable AuthenticationExtensionsCredPropsOutputs credProps, @Param(4) @Nullable AuthenticationExtensionsPrfOutputs prfOutputs, @Param(5) @Nullable String txAuthSimple) {
this.uvmEntries = uvmEntries;
this.devicePublicKeyOutputs = devicePublicKeyOutputs;
this.credProps = credProps;
this.prfOutputs = prfOutputs;
this.txAuthSimple = txAuthSimple;
}
@Nullable
public UvmEntries getUvmEntries() {
return uvmEntries;
}
@Nullable
public AuthenticationExtensionsDevicePublicKeyOutputs getDevicePublicKeyOutputs() {
return devicePublicKeyOutputs;
}
@Nullable
public AuthenticationExtensionsCredPropsOutputs getCredProps() {
return credProps;
}
@Nullable
public AuthenticationExtensionsPrfOutputs getPrfOutputs() {
return prfOutputs;
}
@Nullable
public String getTxAuthSimple() {
return txAuthSimple;
}
/**
* Serializes the {@link AuthenticationExtensionsClientOutputs} to bytes.
* Use {@link #deserializeFromBytes(byte[])} to deserialize.
*/
@NonNull
public byte[] serializeToBytes() {
return SafeParcelableSerializer.serializeToBytes(this);
}
/**
* De-serializes the {@link AuthenticationExtensionsClientOutputs} from bytes, reversing {@link #serializeToBytes()}.
*
* @return The deserialized {@link AuthenticationExtensionsClientOutputs}
*/
@NonNull
public static AuthenticationExtensionsClientOutputs deserializeFromBytes(byte[] serializedBytes) {
return SafeParcelableSerializer.deserializeFromBytes(serializedBytes, CREATOR);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof AuthenticationExtensionsClientOutputs)) return false;
AuthenticationExtensionsClientOutputs that = (AuthenticationExtensionsClientOutputs) o;
return (Objects.equals(uvmEntries, that.uvmEntries)) && (Objects.equals(devicePublicKeyOutputs, that.devicePublicKeyOutputs)) && (Objects.equals(credProps, that.credProps)) && (Objects.equals(prfOutputs, that.prfOutputs)) && (Objects.equals(txAuthSimple, that.txAuthSimple));
}
@Override
public int hashCode() {
return Arrays.hashCode(new Object[]{uvmEntries, devicePublicKeyOutputs, credProps, prfOutputs, txAuthSimple});
}
/**
* Builder for {@link AuthenticationExtensionsClientOutputs}.
*/
public static class Builder {
@Nullable
private UvmEntries uvmEntries;
@Nullable
private AuthenticationExtensionsDevicePublicKeyOutputs devicePublicKeyOutputs;
@Nullable
private AuthenticationExtensionsCredPropsOutputs credProps;
@Nullable
private AuthenticationExtensionsPrfOutputs prfOutputs;
@Nullable
private String txAuthSimple;
/**
* The constructor of {@link AuthenticationExtensionsClientOutputs.Builder}.
*/
public Builder() {
}
/**
* Sets the User Verification Method extension, which allows the relying party to ascertain up to three
* authentication methods that were used.
*/
public Builder setUserVerificationMethodEntries(@Nullable UvmEntries uvmEntries) {
this.uvmEntries = uvmEntries;
return this;
}
/**
* Set Device Public Key client outputs
*/
public Builder setDevicePublicKeyOutputs(@Nullable AuthenticationExtensionsDevicePublicKeyOutputs dpkOutputs) {
this.devicePublicKeyOutputs = dpkOutputs;
return this;
}
/**
* Set Credential Properties client outputs (e.g., rk=true)
*/
public Builder setCredProps(@Nullable AuthenticationExtensionsCredPropsOutputs credProps) {
this.credProps = credProps;
return this;
}
/**
* Set PRF client outputs
*/
public Builder setPrfOutputs(@Nullable AuthenticationExtensionsPrfOutputs prfOutputs) {
this.prfOutputs = prfOutputs;
return this;
}
/**
* Set txAuthSimple string
*/
public Builder setTxAuthSimple(@Nullable String txAuthSimple) {
this.txAuthSimple = txAuthSimple;
return this;
}
/**
* Builds the {@link AuthenticationExtensionsClientOutputs} object.
*/
public AuthenticationExtensionsClientOutputs build() {
return new AuthenticationExtensionsClientOutputs(uvmEntries, devicePublicKeyOutputs, credProps, prfOutputs, txAuthSimple);
}
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
CREATOR.writeToParcel(this, dest, flags);
}
public static final SafeParcelableCreatorAndWriter<AuthenticationExtensionsClientOutputs> CREATOR = findCreator(AuthenticationExtensionsClientOutputs.class);
}

View file

@ -0,0 +1,55 @@
/*
* SPDX-FileCopyrightText: 2023 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.fido.fido2.api.common;
import android.os.Parcel;
import androidx.annotation.NonNull;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import java.util.Objects;
/**
* Class that holds the result of the credProps extension.
* <p>
* Since this extension only reports information, it is always included in registration responses and does not need to be requested.
*/
@SafeParcelable.Class
public class AuthenticationExtensionsCredPropsOutputs extends AbstractSafeParcelable {
@Field(value = 1, getterName = "getIsDiscoverableCredential")
private boolean rk;
@Constructor
public AuthenticationExtensionsCredPropsOutputs(@Param(1) boolean rk) {
this.rk = rk;
}
public boolean equals(Object other) {
return (other instanceof AuthenticationExtensionsCredPropsOutputs) && this.rk == ((AuthenticationExtensionsCredPropsOutputs) other).rk;
}
/**
* This value reflects the "rk" flag of the WebAuthn extension.
*/
public boolean getIsDiscoverableCredential() {
return rk;
}
public int hashCode() {
return Objects.hashCode(new Object[]{this.rk});
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
CREATOR.writeToParcel(this, dest, flags);
}
public static final SafeParcelableCreatorAndWriter<AuthenticationExtensionsCredPropsOutputs> CREATOR = findCreator(AuthenticationExtensionsCredPropsOutputs.class);
}

View file

@ -0,0 +1,111 @@
/*
* SPDX-FileCopyrightText: 2025 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.google.android.gms.fido.fido2.api.common;
import android.os.Parcel;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableSerializer;
import org.microg.gms.common.PublicApi;
import org.microg.gms.utils.ToStringHelper;
import java.util.Arrays;
@PublicApi
@SafeParcelable.Class
public class AuthenticationExtensionsDevicePublicKeyOutputs extends AbstractSafeParcelable {
@Field(value = 1, getterName = "getDevicePublicKey")
@Nullable
private final byte[] devicePublicKey;
@Field(value = 2, getterName = "getSignature")
@Nullable
private final byte[] signature;
@Constructor
public AuthenticationExtensionsDevicePublicKeyOutputs(@Param(1) byte[] devicePublicKey, @Param(2) byte[] signature) {
this.devicePublicKey = devicePublicKey;
this.signature = signature;
}
@Nullable
public byte[] getDevicePublicKey() {
return devicePublicKey;
}
@Nullable
public byte[] getSignature() {
return signature;
}
@PublicApi
public static class Builder {
@Nullable
private byte[] devicePublicKey;
@Nullable
private byte[] signature;
public Builder() {
}
public Builder setDevicePublicKey(@Nullable byte[] devicePublicKey) {
this.devicePublicKey = devicePublicKey;
return this;
}
public Builder setSignature(@Nullable byte[] signature) {
this.signature = signature;
return this;
}
public AuthenticationExtensionsDevicePublicKeyOutputs build() {
return new AuthenticationExtensionsDevicePublicKeyOutputs(devicePublicKey, signature);
}
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
CREATOR.writeToParcel(this, dest, flags);
}
@PublicApi
@NonNull
public byte[] serializeToBytes() {
return SafeParcelableSerializer.serializeToBytes(this);
}
@PublicApi
@NonNull
public static AuthenticationExtensionsDevicePublicKeyOutputs deserializeFromBytes(@NonNull byte[] serializedBytes) {
return SafeParcelableSerializer.deserializeFromBytes(serializedBytes, CREATOR);
}
@Override
public boolean equals(Object o) {
if (!(o instanceof AuthenticationExtensionsDevicePublicKeyOutputs)) return false;
AuthenticationExtensionsDevicePublicKeyOutputs that = (AuthenticationExtensionsDevicePublicKeyOutputs) o;
return Arrays.equals(devicePublicKey, that.devicePublicKey) && Arrays.equals(signature, that.signature);
}
@Override
public int hashCode() {
return Arrays.hashCode(new Object[]{Arrays.hashCode(devicePublicKey), Arrays.hashCode(signature)});
}
@Override
public String toString() {
return ToStringHelper.name("AuthenticationExtensionsDevicePublicKeyOutputs").field("devicePublicKey", devicePublicKey != null ? devicePublicKey.length : null).field("signature", signature != null ? signature.length : null).end();
}
public static final SafeParcelableCreatorAndWriter<AuthenticationExtensionsDevicePublicKeyOutputs> CREATOR = findCreator(AuthenticationExtensionsDevicePublicKeyOutputs.class);
}

View file

@ -0,0 +1,70 @@
/*
* SPDX-FileCopyrightText: 2025 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.google.android.gms.fido.fido2.api.common;
import android.os.Parcel;
import android.util.Base64;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import org.microg.gms.utils.ToStringHelper;
@SafeParcelable.Class
public class AuthenticationExtensionsPrfOutputs extends AbstractSafeParcelable {
@Field(value = 1, getterName = "isEnabled")
private final boolean enabled;
@Field(value = 2, getterName = "getFirst")
@Nullable
private final byte[] first;
@Field(value = 3, getterName = "getSecond")
@Nullable
private final byte[] second;
@Constructor
public AuthenticationExtensionsPrfOutputs(@Param(1) boolean enabled, @Param(2) @Nullable byte[] first, @Param(3) @Nullable byte[] second) {
this.enabled = enabled;
this.first = first;
this.second = second;
}
public boolean isEnabled() {
return enabled;
}
@Nullable
public byte[] getFirst() {
return first;
}
@Nullable
public byte[] getSecond() {
return second;
}
private String b64url(byte[] v) {
return Base64.encodeToString(v, Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING);
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
CREATOR.writeToParcel(this, dest, flags);
}
public static final SafeParcelableCreatorAndWriter<AuthenticationExtensionsPrfOutputs> CREATOR = findCreator(AuthenticationExtensionsPrfOutputs.class);
@Override
public String toString() {
return ToStringHelper.name("AuthenticationExtensionsPrfOutputs").field("enabled", enabled).field("first", first).field("second", second).end();
}
}

View file

@ -0,0 +1,135 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.fido.fido2.api.common;
import android.os.Parcel;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableSerializer;
import org.microg.gms.common.PublicApi;
import org.microg.gms.utils.ToStringHelper;
import java.util.Arrays;
/**
* This structure contains cryptographic signatures produced by scoped credentials that provides proof of possession
* of a private key as well as evidence of user consent to a specific transaction.
*/
@PublicApi
@SafeParcelable.Class
public class AuthenticatorAssertionResponse extends AuthenticatorResponse {
@Field(value = 2, getterName = "getKeyHandle")
@NonNull
private byte[] keyHandle;
@Field(value = 3, getterName = "getClientDataJSON")
@NonNull
private byte[] clientDataJSON;
@Field(value = 4, getterName = "getAuthenticatorData")
@NonNull
private byte[] authenticatorData;
@Field(value = 5, getterName = "getSignature")
@NonNull
private byte[] signature;
@Field(value = 6, getterName = "getUserHandle")
@Nullable
private byte[] userHandle;
private AuthenticatorAssertionResponse() {
}
@Constructor
public AuthenticatorAssertionResponse(@Param(2) @NonNull byte[] keyHandle, @Param(3) @NonNull byte[] clientDataJSON, @Param(4) @NonNull byte[] authenticatorData, @Param(5) @NonNull byte[] signature, @Param(6) @Nullable byte[] userHandle) {
this.keyHandle = keyHandle;
this.clientDataJSON = clientDataJSON;
this.authenticatorData = authenticatorData;
this.signature = signature;
this.userHandle = userHandle;
}
@NonNull
public byte[] getAuthenticatorData() {
return authenticatorData;
}
@Override
@NonNull
public byte[] getClientDataJSON() {
return clientDataJSON;
}
/**
* @deprecated use {@link PublicKeyCredential#getRawId()} instead
*/
@Deprecated
@NonNull
public byte[] getKeyHandle() {
return keyHandle;
}
@NonNull
public byte[] getSignature() {
return signature;
}
@Nullable
public byte[] getUserHandle() {
return userHandle;
}
@Override
@NonNull
public byte[] serializeToBytes() {
return SafeParcelableSerializer.serializeToBytes(this);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof AuthenticatorAssertionResponse)) return false;
AuthenticatorAssertionResponse that = (AuthenticatorAssertionResponse) o;
if (!Arrays.equals(keyHandle, that.keyHandle)) return false;
if (!Arrays.equals(clientDataJSON, that.clientDataJSON)) return false;
if (!Arrays.equals(authenticatorData, that.authenticatorData)) return false;
if (!Arrays.equals(signature, that.signature)) return false;
return Arrays.equals(userHandle, that.userHandle);
}
@Override
public int hashCode() {
return Arrays.hashCode(new Object[]{Arrays.hashCode(keyHandle), Arrays.hashCode(clientDataJSON), Arrays.hashCode(authenticatorData), Arrays.hashCode(signature), Arrays.hashCode(userHandle)});
}
@Override
@NonNull
public String toString() {
return ToStringHelper.name("AuthenticatorAssertionResponse")
.field("keyHandle", keyHandle)
.field("clientDataJSON", clientDataJSON)
.field("authenticatorData", authenticatorData)
.field("signature", signature)
.field("userHandle", userHandle)
.end();
}
@NonNull
public static AuthenticatorAssertionResponse deserializeFromBytes(byte[] serializedBytes) {
return SafeParcelableSerializer.deserializeFromBytes(serializedBytes, CREATOR);
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
CREATOR.writeToParcel(this, dest, flags);
}
public static final SafeParcelableCreatorAndWriter<AuthenticatorAssertionResponse> CREATOR = findCreator(AuthenticatorAssertionResponse.class);
}

View file

@ -0,0 +1,125 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.fido.fido2.api.common;
import android.os.Parcel;
import androidx.annotation.NonNull;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableSerializer;
import org.microg.gms.common.Hide;
import org.microg.gms.common.PublicApi;
import org.microg.gms.utils.ToStringHelper;
import java.util.Arrays;
/**
* Represents a newly-created scoped credential, aka the response from a registration request.
*/
@PublicApi
@SafeParcelable.Class
public class AuthenticatorAttestationResponse extends AuthenticatorResponse {
@Field(value = 2, getterName = "getKeyHandle")
@NonNull
private byte[] keyHandle;
@Field(value = 3, getterName = "getClientDataJSON")
@NonNull
private byte[] clientDataJSON;
@Field(value = 4, getterName = "getAttestationObject")
@NonNull
private byte[] attestationObject;
@Field(value = 5, getterName = "getTransports")
@NonNull
private String[] transports;
private AuthenticatorAttestationResponse() {
}
@Hide
@Constructor
public AuthenticatorAttestationResponse(@Param(2) @NonNull byte[] keyHandle, @Param(3) @NonNull byte[] clientDataJSON, @Param(4) @NonNull byte[] attestationObject, @Param(5) @NonNull String[] transports) {
this.keyHandle = keyHandle;
this.clientDataJSON = clientDataJSON;
this.attestationObject = attestationObject;
this.transports = transports;
}
@NonNull
public byte[] getAttestationObject() {
return attestationObject;
}
@Override
@NonNull
public byte[] getClientDataJSON() {
return clientDataJSON;
}
/**
* @deprecated use {@link PublicKeyCredential#getRawId()} instead
*/
@Deprecated
@NonNull
public byte[] getKeyHandle() {
return keyHandle;
}
@NonNull
public String[] getTransports() {
return transports;
}
@Override
@NonNull
public byte[] serializeToBytes() {
return SafeParcelableSerializer.serializeToBytes(this);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof AuthenticatorAttestationResponse)) return false;
AuthenticatorAttestationResponse that = (AuthenticatorAttestationResponse) o;
if (!Arrays.equals(keyHandle, that.keyHandle)) return false;
if (!Arrays.equals(clientDataJSON, that.clientDataJSON)) return false;
if (!Arrays.equals(attestationObject, that.attestationObject)) return false;
if (!Arrays.equals(transports, that.transports)) return false;
return true;
}
@Override
public int hashCode() {
return Arrays.hashCode(new Object[]{Arrays.hashCode(keyHandle), Arrays.hashCode(clientDataJSON), Arrays.hashCode(attestationObject), Arrays.hashCode(transports)});
}
@Override
@NonNull
public String toString() {
return ToStringHelper.name("AuthenticatorAttestationResponse")
.field("keyHandle", keyHandle)
.field("clientDataJSON", clientDataJSON)
.field("attestationObject", attestationObject)
.field("transports", transports)
.end();
}
@NonNull
public static AuthenticatorAttestationResponse deserializeFromBytes(byte[] serializedBytes) {
return SafeParcelableSerializer.deserializeFromBytes(serializedBytes, CREATOR);
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
CREATOR.writeToParcel(this, dest, flags);
}
public static final SafeParcelableCreatorAndWriter<AuthenticatorAttestationResponse> CREATOR = findCreator(AuthenticatorAttestationResponse.class);
}

View file

@ -0,0 +1,123 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.fido.fido2.api.common;
import android.os.Parcel;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableSerializer;
import org.microg.gms.common.Hide;
import org.microg.gms.common.PublicApi;
import org.microg.gms.utils.ToStringHelper;
import java.util.Arrays;
/**
* The response after an error occurred.
*/
@PublicApi
@SafeParcelable.Class
public class AuthenticatorErrorResponse extends AuthenticatorResponse {
@Field(value = 2, getterName = "getErrorCode")
@NonNull
private ErrorCode errorCode;
@Field(value = 3, getterName = "getErrorMessage")
@Nullable
private String errorMessage;
@Field(value = 4, getterName = "getInternalErrorCode")
private int internalErrorCode;
private AuthenticatorErrorResponse() {
}
@Hide
public AuthenticatorErrorResponse(@NonNull ErrorCode errorCode, @Nullable String errorMessage) {
this.errorCode = errorCode;
this.errorMessage = errorMessage;
}
@Constructor
AuthenticatorErrorResponse(@Param(2) @NonNull ErrorCode errorCode, @Param(3) @Nullable String errorMessage, @Param(4) int internalErrorCode) {
this.errorCode = errorCode;
this.errorMessage = errorMessage;
this.internalErrorCode = internalErrorCode;
}
@Override
@NonNull
public byte[] getClientDataJSON() {
throw new UnsupportedOperationException();
}
@NonNull
public ErrorCode getErrorCode() {
return errorCode;
}
public int getErrorCodeAsInt() {
return errorCode.getCode();
}
@Nullable
public String getErrorMessage() {
return errorMessage;
}
@Hide
public int getInternalErrorCode() {
return internalErrorCode;
}
@Override
@NonNull
public byte[] serializeToBytes() {
return SafeParcelableSerializer.serializeToBytes(this);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof AuthenticatorErrorResponse)) return false;
AuthenticatorErrorResponse that = (AuthenticatorErrorResponse) o;
if (errorCode != null ? !errorCode.equals(that.errorCode) : that.errorCode != null) return false;
if (errorMessage != null ? !errorMessage.equals(that.errorMessage) : that.errorMessage != null) return false;
if (internalErrorCode != that.internalErrorCode) return false;
return true;
}
@Override
public int hashCode() {
return Arrays.hashCode(new Object[]{errorCode, errorMessage, internalErrorCode});
}
@Override
@NonNull
public String toString() {
return ToStringHelper.name("AuthenticatorErrorResponse")
.value(errorCode.name())
.value(errorMessage)
.end();
}
@NonNull
public static AuthenticatorErrorResponse deserializeFromBytes(byte[] serializedBytes) {
return SafeParcelableSerializer.deserializeFromBytes(serializedBytes, CREATOR);
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
CREATOR.writeToParcel(this, dest, flags);
}
public static final SafeParcelableCreatorAndWriter<AuthenticatorErrorResponse> CREATOR = findCreator(AuthenticatorErrorResponse.class);
}

View file

@ -0,0 +1,23 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.fido.fido2.api.common;
import androidx.annotation.NonNull;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
/**
* Authenticators respond to relying party requests by returning an object derived from this interface.
*/
public abstract class AuthenticatorResponse extends AbstractSafeParcelable {
@NonNull
public abstract byte[] getClientDataJSON();
@NonNull
public abstract byte[] serializeToBytes();
}

View file

@ -0,0 +1,159 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.fido.fido2.api.common;
import android.os.Parcel;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import org.microg.gms.common.Hide;
import org.microg.gms.utils.ToStringHelper;
import java.util.Arrays;
/**
* Relying Parties may use {@link AuthenticatorSelectionCriteria} to specify their requirements regarding authenticator
* attributes.
*/
@SafeParcelable.Class
public class AuthenticatorSelectionCriteria extends AbstractSafeParcelable {
@Field(value = 2, getterName = "getAttachment")
@Nullable
private Attachment attachment;
@Field(value = 3, getterName = "getRequireResidentKey")
@Nullable
private Boolean requireResidentKey;
@Field(value = 4, getterName = "getRequireUserVerification")
@Nullable
private UserVerificationRequirement requireUserVerification;
@Field(value = 5, getterName = "getResidentKeyRequirement")
@Nullable
private ResidentKeyRequirement residentKeyRequirement;
@Constructor
AuthenticatorSelectionCriteria(@Param(2) @Nullable Attachment attachment, @Param(3) @Nullable Boolean requireResidentKey, @Param(4) @Nullable UserVerificationRequirement requireUserVerification, @Param(5) @Nullable ResidentKeyRequirement residentKeyRequirement) {
this.attachment = attachment;
this.requireResidentKey = requireResidentKey;
this.requireUserVerification = requireUserVerification;
this.residentKeyRequirement = residentKeyRequirement;
}
@Nullable
public Attachment getAttachment() {
return attachment;
}
@Nullable
public String getAttachmentAsString() {
if (attachment == null) return null;
return attachment.toString();
}
@Nullable
public Boolean getRequireResidentKey() {
return requireResidentKey;
}
@Nullable
public ResidentKeyRequirement getResidentKeyRequirement() {
return residentKeyRequirement;
}
@Nullable
public String getResidentKeyRequirementAsString() {
if (residentKeyRequirement == null) return null;
return residentKeyRequirement.toString();
}
@Hide
@Nullable
public UserVerificationRequirement getRequireUserVerification() {
return requireUserVerification;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof AuthenticatorSelectionCriteria)) return false;
AuthenticatorSelectionCriteria that = (AuthenticatorSelectionCriteria) o;
if (attachment != that.attachment) return false;
if (requireResidentKey != null ? !requireResidentKey.equals(that.requireResidentKey) : that.requireResidentKey != null) return false;
if (requireUserVerification != that.requireUserVerification) return false;
if (residentKeyRequirement != that.residentKeyRequirement) return false;
return true;
}
@Override
public int hashCode() {
return Arrays.hashCode(new Object[]{attachment, requireResidentKey, requireUserVerification});
}
@Override
@NonNull
public String toString() {
return ToStringHelper.name("AuthenticatorSelectionCriteria")
.field("attachment", attachment)
.field("requireResidentKey", requireResidentKey)
.field("requireUserVerification", requireUserVerification)
.field("residentKeyRequirement", residentKeyRequirement)
.end();
}
/**
* Builder for {@link AuthenticatorSelectionCriteria}.
*/
public static class Builder {
@Nullable
private Attachment attachment;
@Nullable
private Boolean requireResidentKey;
@Nullable
private ResidentKeyRequirement residentKeyRequirement;
/**
* Sets the attachment to use for this session.
*/
public Builder setAttachment(@Nullable Attachment attachment) {
this.attachment = attachment;
return this;
}
/**
* Sets whether the key created will be a resident key.
*/
public Builder setRequireResidentKey(@Nullable Boolean requireResidentKey) {
this.requireResidentKey = requireResidentKey;
return this;
}
/**
* Sets residentKeyRequirement
*/
public Builder setResidentKeyRequirement(@Nullable ResidentKeyRequirement residentKeyRequirement) {
this.residentKeyRequirement = residentKeyRequirement;
return this;
}
@NonNull
public AuthenticatorSelectionCriteria build() {
return new AuthenticatorSelectionCriteria(attachment, requireResidentKey, null, residentKeyRequirement);
}
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
CREATOR.writeToParcel(this, dest, flags);
}
public static final SafeParcelableCreatorAndWriter<AuthenticatorSelectionCriteria> CREATOR = findCreator(AuthenticatorSelectionCriteria.class);
}

View file

@ -0,0 +1,186 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.google.android.gms.fido.fido2.api.common;
import android.net.Uri;
import android.os.Parcel;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableSerializer;
import org.microg.gms.common.Hide;
import org.microg.gms.common.PublicApi;
import org.microg.gms.utils.ToStringHelper;
import java.util.Arrays;
/**
* Parameters to a make credential request from a Web browser.
*/
@PublicApi
@SafeParcelable.Class
public class BrowserPublicKeyCredentialCreationOptions extends BrowserRequestOptions {
@Field(value = 2, getterName = "getPublicKeyCredentialCreationOptions")
@NonNull
private PublicKeyCredentialCreationOptions delegate;
@Field(value = 3, getterName = "getOrigin")
@NonNull
private Uri origin;
@Field(value = 4, getterName = "getClientDataHash")
@Nullable
private byte[] clientDataHash;
@Constructor
BrowserPublicKeyCredentialCreationOptions(@Param(2) @NonNull PublicKeyCredentialCreationOptions delegate, @Param(3) @NonNull Uri origin, @Param(4) @Nullable byte[] clientDataHash) {
this.delegate = delegate;
this.origin = origin;
this.clientDataHash = clientDataHash;
}
@Override
@Nullable
public AuthenticationExtensions getAuthenticationExtensions() {
return delegate.getAuthenticationExtensions();
}
@Override
@NonNull
public byte[] getChallenge() {
return delegate.getChallenge();
}
@Override
@Nullable
public byte[] getClientDataHash() {
return clientDataHash;
}
@Override
@NonNull
public Uri getOrigin() {
return origin;
}
@NonNull
public PublicKeyCredentialCreationOptions getPublicKeyCredentialCreationOptions() {
return delegate;
}
@Override
@Nullable
public Integer getRequestId() {
return delegate.getRequestId();
}
@Override
@Nullable
public Double getTimeoutSeconds() {
return delegate.getTimeoutSeconds();
}
@Override
@Nullable
public TokenBinding getTokenBinding() {
return delegate.getTokenBinding();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof BrowserPublicKeyCredentialCreationOptions)) return false;
BrowserPublicKeyCredentialCreationOptions that = (BrowserPublicKeyCredentialCreationOptions) o;
if (delegate != null ? !delegate.equals(that.delegate) : that.delegate != null) return false;
if (origin != null ? !origin.equals(that.origin) : that.origin != null) return false;
return Arrays.equals(clientDataHash, that.clientDataHash);
}
@Override
public int hashCode() {
return Arrays.hashCode(new Object[]{delegate, origin, Arrays.hashCode(clientDataHash)});
}
@Override
public String toString() {
return ToStringHelper.name("BrowserPublicKeyCredentialCreationOptions")
.value(delegate)
.field("origin", origin)
.field("clientDataHash", clientDataHash)
.end();
}
/**
* Builder for {@link BrowserPublicKeyCredentialCreationOptions}.
*/
public static class Builder {
@NonNull
private PublicKeyCredentialCreationOptions delegate;
@NonNull
private Uri origin;
@Nullable
private byte[] clientDataHash;
/**
* The constructor of {@link BrowserPublicKeyCredentialCreationOptions.Builder}.
*/
public Builder() {
}
/**
* Sets a clientDataHash value to sign over in place of assembling and hashing clientDataJSON during the
* signature request.
* <p>
* Note: This is optional and only provided for contexts where the unhashed information necessary to assemble
* WebAuthn clientDataJSON is not available. If set, the resulting {@link AuthenticatorAssertionResponse} will
* return an invalid value for {@code getClientDataJSON()}. Generally, browser clients should use
* {@link PublicKeyCredentialCreationOptions.Builder#setChallenge(byte[])} instead.
*
* @return
*/
public BrowserPublicKeyCredentialCreationOptions.Builder setClientDataHash(@NonNull byte[] clientDataHash) {
this.clientDataHash = clientDataHash;
return this;
}
/**
* Sets the origin on whose behalf the calling browser is requesting a registration operation.
*/
public BrowserPublicKeyCredentialCreationOptions.Builder setOrigin(@NonNull Uri origin) {
this.origin = origin;
return this;
}
/**
* Sets the parameters to dictate the client behavior during this registration session.
*/
public BrowserPublicKeyCredentialCreationOptions.Builder setPublicKeyCredentialCreationOptions(@NonNull PublicKeyCredentialCreationOptions publicKeyCredentialCreationOptions) {
this.delegate = publicKeyCredentialCreationOptions;
return this;
}
/**
* Builds the {@link BrowserPublicKeyCredentialCreationOptions} object.
*/
@NonNull
public BrowserPublicKeyCredentialCreationOptions build() {
return new BrowserPublicKeyCredentialCreationOptions(delegate, origin, clientDataHash);
}
}
public static BrowserPublicKeyCredentialCreationOptions deserializeFromBytes(byte[] serializedBytes) {
return SafeParcelableSerializer.deserializeFromBytes(serializedBytes, CREATOR);
}
@Override
public void writeToParcel(Parcel dest, int flags) {
CREATOR.writeToParcel(this, dest, flags);
}
public static final SafeParcelableCreatorAndWriter<BrowserPublicKeyCredentialCreationOptions> CREATOR = findCreator(BrowserPublicKeyCredentialCreationOptions.class);
}

View file

@ -0,0 +1,186 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.google.android.gms.fido.fido2.api.common;
import android.net.Uri;
import android.os.Parcel;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableSerializer;
import org.microg.gms.common.PublicApi;
import org.microg.gms.utils.ToStringHelper;
import java.util.Arrays;
/**
* Parameters for a signature request from a Web Browser.
*/
@PublicApi
@SafeParcelable.Class
public class BrowserPublicKeyCredentialRequestOptions extends BrowserRequestOptions {
@Field(value = 2, getterName = "getPublicKeyCredentialRequestOptions")
@NonNull
private PublicKeyCredentialRequestOptions delegate;
@Field(value = 3, getterName = "getOrigin")
@NonNull
private Uri origin;
@Field(value = 4, getterName = "getClientDataHash")
@Nullable
private byte[] clientDataHash;
@Constructor
BrowserPublicKeyCredentialRequestOptions(@Param(2) @NonNull PublicKeyCredentialRequestOptions delegate, @Param(3) @NonNull Uri origin, @Param(4) @Nullable byte[] clientDataHash) {
this.delegate = delegate;
this.origin = origin;
this.clientDataHash = clientDataHash;
}
@Override
@Nullable
public AuthenticationExtensions getAuthenticationExtensions() {
return delegate.getAuthenticationExtensions();
}
@Override
@NonNull
public byte[] getChallenge() {
return delegate.getChallenge();
}
@Override
@Nullable
public byte[] getClientDataHash() {
return clientDataHash;
}
@Override
@NonNull
public Uri getOrigin() {
return origin;
}
@NonNull
public PublicKeyCredentialRequestOptions getPublicKeyCredentialRequestOptions() {
return delegate;
}
@Override
@Nullable
public Integer getRequestId() {
return delegate.getRequestId();
}
@Override
@Nullable
public Double getTimeoutSeconds() {
return delegate.getTimeoutSeconds();
}
@Override
@Nullable
public TokenBinding getTokenBinding() {
return delegate.getTokenBinding();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof BrowserPublicKeyCredentialRequestOptions)) return false;
BrowserPublicKeyCredentialRequestOptions that = (BrowserPublicKeyCredentialRequestOptions) o;
if (delegate != null ? !delegate.equals(that.delegate) : that.delegate != null) return false;
if (origin != null ? !origin.equals(that.origin) : that.origin != null) return false;
return Arrays.equals(clientDataHash, that.clientDataHash);
}
@Override
public int hashCode() {
return Arrays.hashCode(new Object[]{delegate, origin, Arrays.hashCode(clientDataHash)});
}
@Override
@NonNull
public String toString() {
return ToStringHelper.name("BrowserPublicKeyCredentialRequestOptions")
.value(delegate)
.field("origin", origin)
.field("clientDataHash", clientDataHash)
.end();
}
/**
* Builder for {@link BrowserPublicKeyCredentialRequestOptions}.
*/
public static class Builder {
@NonNull
private PublicKeyCredentialRequestOptions delegate;
@NonNull
private Uri origin;
@Nullable
private byte[] clientDataHash;
/**
* The constructor of {@link BrowserPublicKeyCredentialRequestOptions.Builder}.
*/
public Builder() {
}
/**
* Sets a clientDataHash value to sign over in place of assembling and hashing clientDataJSON during the
* signature request.
* <p>
* Note: This is optional and only provided for contexts where the unhashed information necessary to assemble
* WebAuthn clientDataJSON is not available. If set, the resulting {@link AuthenticatorAssertionResponse} will
* return an invalid value for {@code getClientDataJSON()}. Generally, browser clients should use
* {@link PublicKeyCredentialRequestOptions.Builder#setChallenge(byte[])} instead.
*
* @return
*/
public Builder setClientDataHash(@NonNull byte[] clientDataHash) {
this.clientDataHash = clientDataHash;
return this;
}
/**
* Sets the origin on whose behalf the calling browser is requesting an authentication operation.
*/
public Builder setOrigin(@NonNull Uri origin) {
this.origin = origin;
return this;
}
/**
* Sets the parameters to dictate client behavior during this authentication session.
*/
public Builder setPublicKeyCredentialRequestOptions(@NonNull PublicKeyCredentialRequestOptions publicKeyCredentialRequestOptions) {
this.delegate = publicKeyCredentialRequestOptions;
return this;
}
/**
* Builds the {@link BrowserPublicKeyCredentialRequestOptions} object.
*/
@NonNull
public BrowserPublicKeyCredentialRequestOptions build() {
return new BrowserPublicKeyCredentialRequestOptions(delegate, origin, clientDataHash);
}
}
public static BrowserPublicKeyCredentialRequestOptions deserializeFromBytes(byte[] serializedBytes) {
return SafeParcelableSerializer.deserializeFromBytes(serializedBytes, CREATOR);
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
CREATOR.writeToParcel(this, dest, flags);
}
public static final SafeParcelableCreatorAndWriter<BrowserPublicKeyCredentialRequestOptions> CREATOR = findCreator(BrowserPublicKeyCredentialRequestOptions.class);
}

View file

@ -0,0 +1,27 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.fido.fido2.api.common;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
/**
* An abstract class representing browser-based request parameters.
*/
public abstract class BrowserRequestOptions extends RequestOptions {
/**
* Gets value of the client data hash.
*/
@Nullable
public abstract byte[] getClientDataHash();
@NonNull
public abstract Uri getOrigin();
}

View file

@ -0,0 +1,84 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.fido.fido2.api.common;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.NonNull;
import org.microg.gms.common.PublicApi;
import org.microg.gms.utils.ToStringHelper;
@PublicApi
public class COSEAlgorithmIdentifier implements Parcelable {
private Algorithm algorithm;
private COSEAlgorithmIdentifier() {
}
private COSEAlgorithmIdentifier(Algorithm algorithm) {
this.algorithm = algorithm;
}
@NonNull
public static COSEAlgorithmIdentifier fromCoseValue(int value) throws UnsupportedAlgorithmIdentifierException {
if (value == RSAAlgorithm.LEGACY_RS1.getAlgoValue()) return new COSEAlgorithmIdentifier(RSAAlgorithm.RS1);
for (RSAAlgorithm algorithm : RSAAlgorithm.values()) {
if (algorithm.getAlgoValue() == value) return new COSEAlgorithmIdentifier(algorithm);
}
for (EC2Algorithm algorithm : EC2Algorithm.values()) {
if (algorithm.getAlgoValue() == value) return new COSEAlgorithmIdentifier(algorithm);
}
throw new UnsupportedAlgorithmIdentifierException(value);
}
public int toCoseValue() {
return algorithm.getAlgoValue();
}
@Override
@NonNull
public String toString() {
return ToStringHelper.name("COSEAlgorithmIdentifier")
.value(algorithm)
.end();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(algorithm.getAlgoValue());
}
public static final Creator<COSEAlgorithmIdentifier> CREATOR = new Creator<COSEAlgorithmIdentifier>() {
@Override
public COSEAlgorithmIdentifier createFromParcel(Parcel in) {
try {
return fromCoseValue(in.readInt());
} catch (UnsupportedAlgorithmIdentifierException e) {
throw new RuntimeException(e);
}
}
@Override
public COSEAlgorithmIdentifier[] newArray(int size) {
return new COSEAlgorithmIdentifier[size];
}
};
public static class UnsupportedAlgorithmIdentifierException extends Exception {
public UnsupportedAlgorithmIdentifierException(int algId) {
super("Algorithm with COSE value " + algId + " not supported");
}
}
}

View file

@ -0,0 +1,34 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.google.android.gms.fido.fido2.api.common;
import android.os.Parcel;
import androidx.annotation.NonNull;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
@SafeParcelable.Class
public class CableAuthenticationData extends AbstractSafeParcelable {
@Field(1)
long version;
@Field(2)
@NonNull
byte[] clientEid;
@Field(3)
@NonNull
byte[] authenticatorEid;
@Field(4)
@NonNull
byte[] sessionPreKey;
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
CREATOR.writeToParcel(this, dest, flags);
}
public static final SafeParcelableCreatorAndWriter<CableAuthenticationData> CREATOR = findCreator(CableAuthenticationData.class);
}

View file

@ -0,0 +1,28 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.google.android.gms.fido.fido2.api.common;
import android.os.Parcel;
import androidx.annotation.NonNull;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import java.util.List;
@SafeParcelable.Class
public class CableAuthenticationExtension extends AbstractSafeParcelable {
@Field(1)
@NonNull
List<CableAuthenticationData> cableAuthentication;
@Override
public void writeToParcel(Parcel dest, int flags) {
CREATOR.writeToParcel(this, dest, flags);
}
public static final SafeParcelableCreatorAndWriter<CableAuthenticationExtension> CREATOR = findCreator(CableAuthenticationExtension.class);
}

View file

@ -0,0 +1,54 @@
/*
* SPDX-FileCopyrightText: 2025 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.google.android.gms.fido.fido2.api.common;
import android.os.Parcel;
import androidx.annotation.NonNull;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import org.microg.gms.common.PublicApi;
import java.util.Arrays;
@PublicApi
@SafeParcelable.Class
public class CredentialPropertiesOutput extends AbstractSafeParcelable {
@Field(value = 1, getterName = "isResidentKey")
private final boolean residentKey;
@Constructor
public CredentialPropertiesOutput(@Param(1) boolean residentKey) {
this.residentKey = residentKey;
}
public boolean isResidentKey() {
return residentKey;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof CredentialPropertiesOutput)) return false;
CredentialPropertiesOutput that = (CredentialPropertiesOutput) o;
return residentKey == that.residentKey;
}
@Override
public int hashCode() {
return Arrays.hashCode(new Object[]{residentKey});
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
CREATOR.writeToParcel(this, dest, flags);
}
public static final SafeParcelableCreatorAndWriter<CredentialPropertiesOutput> CREATOR = findCreator(CredentialPropertiesOutput.class);
}

View file

@ -0,0 +1,45 @@
/*
* SPDX-FileCopyrightText: 2025 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.google.android.gms.fido.fido2.api.common;
import android.os.Parcel;
import androidx.annotation.NonNull;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import org.microg.gms.common.PublicApi;
import org.microg.gms.utils.ToStringHelper;
@PublicApi
@SafeParcelable.Class
public class DevicePublicKeyExtension extends AbstractSafeParcelable {
@Field(value = 1, getterName = "isDevicePublicKey")
private final boolean devicePublicKey;
@Constructor
public DevicePublicKeyExtension(@Param(1) boolean devicePublicKey) {
this.devicePublicKey = devicePublicKey;
}
public boolean isDevicePublicKey() {
return devicePublicKey;
}
@Override
public String toString() {
return ToStringHelper.name("DevicePublicKeyExtension").field("isDevicePublicKey", devicePublicKey).end();
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
CREATOR.writeToParcel(this, dest, flags);
}
public static final SafeParcelableCreatorAndWriter<DevicePublicKeyExtension> CREATOR = AbstractSafeParcelable.findCreator(DevicePublicKeyExtension.class);
}

View file

@ -0,0 +1,30 @@
/*
* SPDX-FileCopyrightText: 2023 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.fido.fido2.api.common;
import androidx.annotation.NonNull;
/**
* Enum values to be passed into DevicePublicKeyExtension. This tells the authenticator what to return for the DPK extension object.
* <p>
* These values are placeholders until the final spec is determined. For now,
* <ul>
* <li>NONE is to not request a DPK.</li>
* <li>DIRECT is to request a DPK.</li>
* <li>INDIRECT has no function at this time.</li>
* </ul>
*/
public @interface DevicePublicKeyStringDef {
@NonNull
String NONE = "none";
@NonNull
String INDIRECT = "indirect";
@NonNull
String DIRECT = "direct";
}

View file

@ -0,0 +1,57 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.fido.fido2.api.common;
import org.microg.gms.common.PublicApi;
/**
* Algorithm names and COSE identifiers for EC2 (public) keys.
*/
@PublicApi
public enum EC2Algorithm implements Algorithm {
/**
* ECDH-ES with HKDF-SHA-256
*/
ECDH_HKDF_256(-25),
/**
* EdDSA with Ed25519
*/
ED25519(-8),
/**
* TPM_ECC_BN_P256 curve w/ SHA-256
*/
ED256(-260),
/**
* ECC_BN_ISOP512 curve w/ SHA-512
*/
ED512(-261),
/**
* ECDSA w/ SHA-256
*/
ES256(-7),
/**
* ECDSA w/ SHA-384
*/
ES384(-35),
/**
* ECDSA w/ SHA-512
*/
ES512(-36);
private final int algoValue;
EC2Algorithm(int algoValue) {
this.algoValue = algoValue;
}
@Override
public int getAlgoValue() {
return algoValue;
}
}

View file

@ -0,0 +1,129 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.fido.fido2.api.common;
import android.os.Parcel;
import android.os.Parcelable;
import org.microg.gms.common.Hide;
import org.microg.gms.common.PublicApi;
/**
* Error codes that are referenced by WebAuthn spec.
*/
@PublicApi
public enum ErrorCode implements Parcelable {
/**
* The operation is not supported.
*/
NOT_SUPPORTED_ERR(9),
/**
* The object is in an invalid state.
*/
INVALID_STATE_ERR(11),
/**
* The operation is insecure.
*/
SECURITY_ERR(18),
/**
* A network error occurred.
*/
NETWORK_ERR(19),
/**
* The operation was aborted.
*/
ABORT_ERR(20),
/**
* The operation timed out.
*/
TIMEOUT_ERR(23),
/**
* The encoding operation (either encoded or decoding) failed.
*/
ENCODING_ERR(27),
/**
* The operation failed for an unknown transient reason.
*/
UNKNOWN_ERR(28),
/**
* A mutation operation in a transaction failed because a constraint was not satisfied.
*/
CONSTRAINT_ERR(29),
/**
* Provided data is inadequate.
*/
DATA_ERR(30),
/**
* The request is not allowed by the user agent or the platform in the current context, possibly because the user
* denied permission.
*/
NOT_ALLOWED_ERR(35),
/**
* The authenticator violates the privacy requirements of the {@code AttestationStatementType} it is using.
*/
ATTESTATION_NOT_PRIVATE_ERR(36);
private int code;
ErrorCode(int code) {
this.code = code;
}
@Hide
public int getCode() {
return code;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(code);
}
@Hide
public static ErrorCode toErrorCode(int errorCode) throws UnsupportedErrorCodeException {
for (ErrorCode value : values()) {
if (value.code == errorCode) return value;
}
throw new UnsupportedErrorCodeException(errorCode);
}
/**
* Exception thrown when an unsupported or unrecognized error code is encountered.
*/
public static class UnsupportedErrorCodeException extends Exception {
/**
* Constructor for the {@link ErrorCode.UnsupportedErrorCodeException}.
*/
public UnsupportedErrorCodeException(int errorCode) {
super("Error code " + errorCode + " is not supported");
}
}
@Hide
public static final Creator<ErrorCode> CREATOR = new Creator<ErrorCode>() {
@Override
public ErrorCode createFromParcel(Parcel source) {
try {
return ErrorCode.toErrorCode(source.readInt());
} catch (UnsupportedErrorCodeException e) {
throw new IllegalArgumentException(e);
}
}
@Override
public ErrorCode[] newArray(int size) {
return new ErrorCode[size];
}
};
}

View file

@ -0,0 +1,70 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.fido.fido2.api.common;
import android.os.Parcel;
import androidx.annotation.NonNull;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import org.microg.gms.common.PublicApi;
import java.util.Arrays;
/**
* Extension for FIDO appId, to support U2F backward compatibility in FIDO2 assertion requests.
* <p>
* This authentication extension allows Relying Parties that have previously registered a credential using the legacy
* FIDO U2F APIs to request an assertion. Specifically, this extension allows Relying Parties to specify an appId to
* overwrite the computed rpId for U2F authenticators.
* <p>
* Note that this extension is only valid if used during the get() call; other usage should result in client error.
*/
@PublicApi
@SafeParcelable.Class
public class FidoAppIdExtension extends AbstractSafeParcelable {
@Field(value = 2, getterName = "getAppId")
@NonNull
private String appId;
private FidoAppIdExtension() {
}
@Constructor
public FidoAppIdExtension(@Param(2) @NonNull String appId) {
this.appId = appId;
}
@NonNull
public String getAppId() {
return appId;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof FidoAppIdExtension)) return false;
FidoAppIdExtension that = (FidoAppIdExtension) o;
return appId.equals(that.appId);
}
@Override
public int hashCode() {
return Arrays.hashCode(new Object[]{appId});
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
CREATOR.writeToParcel(this, dest, flags);
}
public static final SafeParcelableCreatorAndWriter<FidoAppIdExtension> CREATOR = findCreator(FidoAppIdExtension.class);
}

View file

@ -0,0 +1,140 @@
/*
* SPDX-FileCopyrightText: 2023 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.fido.fido2.api.common;
import android.os.Parcel;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableSerializer;
import java.util.Objects;
/**
* Contains the attributes of a single FIDO credential that are returned to the caller in response to a
* {@link Fido2PrivilegedApiClient#getCredentialList(String)} call.
*/
@SafeParcelable.Class
public class FidoCredentialDetails extends AbstractSafeParcelable {
@Field(value = 1, getterName = "getUserName")
@Nullable
private String userName;
@Field(value = 2, getterName = "getUserDisplayName")
@Nullable
private String userDisplayName;
@Field(value = 3, getterName = "getUserId")
@Nullable
private byte[] userId;
@Field(value = 4, getterName = "getCredentialId")
@NonNull
private byte[] credentialId;
@Field(value = 5, getterName = "getIsDiscoverable")
private boolean discoverable;
@Field(value = 6, getterName = "getIsPaymentCredential")
private boolean paymentCredential;
private FidoCredentialDetails() {
}
@Constructor
FidoCredentialDetails(@Nullable @Param(1) String userName, @Nullable @Param(2) String userDisplayName, @Nullable @Param(3) byte[] userId, @NonNull @Param(4) byte[] credentialId, @Param(5) boolean discoverable, @Param(6) boolean paymentCredential) {
this.userName = userName;
this.userDisplayName = userDisplayName;
this.userId = userId;
this.credentialId = credentialId;
this.discoverable = discoverable;
this.paymentCredential = paymentCredential;
}
/**
* De-serializes the {@link FidoCredentialDetails} from bytes, reversing {@link #serializeToBytes()}.
*
* @return The deserialized {@link FidoCredentialDetails}.
*/
@NonNull
public static FidoCredentialDetails deserializeFromBytes(@NonNull byte[] serializedBytes) {
return SafeParcelableSerializer.deserializeFromBytes(serializedBytes, CREATOR);
}
/**
* Returns the credential's credential ID.
*/
@NonNull
public byte[] getCredentialId() {
return credentialId;
}
/**
* Returns true if the credential is discoverable.
*/
public boolean getIsDiscoverable() {
return discoverable;
}
/**
* Returns true if the credential is for payments.
*/
public boolean getIsPaymentCredential() {
return paymentCredential;
}
/**
* Returns the last used time in Unix Epoch Millis.
*/
public long getLastUsedTime() {
throw new UnsupportedOperationException();
}
/**
* Returns the credential's user display name.
*/
@Nullable
public String getUserDisplayName() {
return userDisplayName;
}
/**
* Returns the credential's user ID.
*/
@Nullable
public byte[] getUserId() {
return userId;
}
/**
* Returns the credential's user name.
*/
@Nullable
public String getUserName() {
return this.userName;
}
public int hashCode() {
return Objects.hashCode(new Object[]{this.userName, this.userDisplayName, this.userId, this.credentialId, this.discoverable, this.paymentCredential});
}
/**
* Serializes the {@link FidoCredentialDetails} to bytes. Use {@link #deserializeFromBytes(byte[])} to deserialize.
*
* @return the serialized byte array.
*/
@NonNull
public byte[] serializeToBytes() {
return SafeParcelableSerializer.serializeToBytes(this);
}
@Override
public void writeToParcel(Parcel out, int flags) {
CREATOR.writeToParcel(this, out, flags);
}
public static final SafeParcelableCreatorAndWriter<FidoCredentialDetails> CREATOR = findCreator(FidoCredentialDetails.class);
}

View file

@ -0,0 +1,39 @@
/*
* SPDX-FileCopyrightText: 2025 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.google.android.gms.fido.fido2.api.common;
import android.os.Parcel;
import androidx.annotation.NonNull;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import org.microg.gms.common.PublicApi;
@PublicApi
@SafeParcelable.Class
public class GoogleMultiAssertionExtension extends AbstractSafeParcelable {
@Field(value = 1, getterName = "isRequestForMultiAssertion")
private final boolean requestForMultiAssertion;
@Constructor
public GoogleMultiAssertionExtension(@Param(1) boolean requestForMultiAssertion) {
this.requestForMultiAssertion = requestForMultiAssertion;
}
public boolean isRequestForMultiAssertion() {
return requestForMultiAssertion;
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
CREATOR.writeToParcel(this, dest, flags);
}
public static final SafeParcelableCreatorAndWriter<GoogleMultiAssertionExtension> CREATOR = AbstractSafeParcelable.findCreator(GoogleMultiAssertionExtension.class);
}

View file

@ -0,0 +1,45 @@
/*
* SPDX-FileCopyrightText: 2025 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.google.android.gms.fido.fido2.api.common;
import android.os.Parcel;
import androidx.annotation.NonNull;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import org.microg.gms.common.PublicApi;
import org.microg.gms.utils.ToStringHelper;
@PublicApi
@SafeParcelable.Class
public class GoogleSessionIdExtension extends AbstractSafeParcelable {
@Field(value = 1, getterName = "getSessionId")
private final long sessionId;
@Constructor
public GoogleSessionIdExtension(@Param(1) long sessionId) {
this.sessionId = sessionId;
}
public long getSessionId() {
return sessionId;
}
@Override
public String toString() {
return ToStringHelper.name("GoogleSessionIdExtension").field("sessionId", sessionId).end();
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
CREATOR.writeToParcel(this, dest, flags);
}
public static final SafeParcelableCreatorAndWriter<GoogleSessionIdExtension> CREATOR = AbstractSafeParcelable.findCreator(GoogleSessionIdExtension.class);
}

View file

@ -0,0 +1,45 @@
/*
* SPDX-FileCopyrightText: 2025 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.google.android.gms.fido.fido2.api.common;
import android.os.Parcel;
import androidx.annotation.NonNull;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import org.microg.gms.common.PublicApi;
import org.microg.gms.utils.ToStringHelper;
@PublicApi
@SafeParcelable.Class
public class GoogleSilentVerificationExtension extends AbstractSafeParcelable {
@Field(value = 1, getterName = "isSilentVerification")
private final boolean silentVerification;
@Constructor
public GoogleSilentVerificationExtension(@Param(1) boolean silentVerification) {
this.silentVerification = silentVerification;
}
public boolean isSilentVerification() {
return silentVerification;
}
@Override
public String toString() {
return ToStringHelper.name("GoogleSilentVerificationExtension").field("silentVerification", silentVerification).end();
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
CREATOR.writeToParcel(this, dest, flags);
}
public static final SafeParcelableCreatorAndWriter<GoogleSilentVerificationExtension> CREATOR = AbstractSafeParcelable.findCreator(GoogleSilentVerificationExtension.class);
}

View file

@ -0,0 +1,45 @@
/*
* SPDX-FileCopyrightText: 2025 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.google.android.gms.fido.fido2.api.common;
import android.os.Parcel;
import androidx.annotation.NonNull;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import org.microg.gms.common.PublicApi;
import org.microg.gms.utils.ToStringHelper;
@PublicApi
@SafeParcelable.Class
public class GoogleThirdPartyPaymentExtension extends AbstractSafeParcelable {
@Field(value = 1, getterName = "isThirdPartyPayment")
private final boolean thirdPartyPayment;
@Constructor
public GoogleThirdPartyPaymentExtension(@Param(1) boolean thirdPartyPayment) {
this.thirdPartyPayment = thirdPartyPayment;
}
public boolean isThirdPartyPayment() {
return thirdPartyPayment;
}
@Override
public String toString() {
return ToStringHelper.name("GoogleThirdPartyPaymentExtension").field("thirdPartyPayment", thirdPartyPayment).end();
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
CREATOR.writeToParcel(this, dest, flags);
}
public static final SafeParcelableCreatorAndWriter<GoogleThirdPartyPaymentExtension> CREATOR = AbstractSafeParcelable.findCreator(GoogleThirdPartyPaymentExtension.class);
}

View file

@ -0,0 +1,47 @@
/*
* SPDX-FileCopyrightText: 2025 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.google.android.gms.fido.fido2.api.common;
import android.os.Parcel;
import androidx.annotation.NonNull;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import org.microg.gms.common.PublicApi;
import org.microg.gms.utils.ToStringHelper;
@PublicApi
@SafeParcelable.Class
public class GoogleTunnelServerIdExtension extends AbstractSafeParcelable {
@Field(value = 1, getterName = "getTunnelServerId")
@NonNull
private final String tunnelServerId;
@Constructor
public GoogleTunnelServerIdExtension(@Param(1) @NonNull String tunnelServerId) {
this.tunnelServerId = tunnelServerId;
}
@NonNull
public String getTunnelServerId() {
return tunnelServerId;
}
@Override
public String toString() {
return ToStringHelper.name("GoogleTunnelServerIdExtension").field("tunnelServerId", tunnelServerId).end();
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
CREATOR.writeToParcel(this, dest, flags);
}
public static final SafeParcelableCreatorAndWriter<GoogleTunnelServerIdExtension> CREATOR = AbstractSafeParcelable.findCreator(GoogleTunnelServerIdExtension.class);
}

View file

@ -0,0 +1,70 @@
/*
* SPDX-FileCopyrightText: 2025 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.google.android.gms.fido.fido2.api.common;
import android.os.Parcel;
import androidx.annotation.NonNull;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import org.microg.gms.common.PublicApi;
import org.microg.gms.utils.ToStringHelper;
@PublicApi
@SafeParcelable.Class
public class HmacSecretExtension extends AbstractSafeParcelable {
@Field(value = 1, getterName = "getCoseKeyAgreement")
private final byte[] coseKeyAgreement;
@Field(value = 2, getterName = "getSaltEnc")
private final byte[] saltEnc;
@Field(value = 3, getterName = "getSaltAuth")
private final byte[] saltAuth;
@Field(value = 4, getterName = "getPinUvAuthProtocol")
private final int pinUvAuthProtocol;
@Constructor
public HmacSecretExtension(@Param(1) byte[] coseKeyAgreement, @Param(2) byte[] saltEnc, @Param(3) byte[] saltAuth, @Param(4) int pinUvAuthProtocol) {
this.coseKeyAgreement = coseKeyAgreement;
this.saltEnc = saltEnc;
this.saltAuth = saltAuth;
this.pinUvAuthProtocol = pinUvAuthProtocol;
}
public byte[] getCoseKeyAgreement() {
return coseKeyAgreement;
}
public byte[] getSaltEnc() {
return saltEnc;
}
public byte[] getSaltAuth() {
return saltAuth;
}
public int getPinUvAuthProtocol() {
return pinUvAuthProtocol;
}
@Override
public String toString() {
return ToStringHelper.name("HmacSecretExtension").field("coseKeyAgreement", coseKeyAgreement == null ? "" : coseKeyAgreement.length).field("saltEnc", saltEnc == null ? "" : saltEnc.length).field("saltAuth", saltAuth == null ? "" : saltAuth.length).field("pinUvAuthProtocol", pinUvAuthProtocol).end();
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
CREATOR.writeToParcel(this, dest, flags);
}
public static final SafeParcelableCreatorAndWriter<HmacSecretExtension> CREATOR = AbstractSafeParcelable.findCreator(HmacSecretExtension.class);
}

View file

@ -0,0 +1,47 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.fido.fido2.api.common;
/**
* The method used by the authenticator to protect the FIDO registration private key material. Available values are
* defined in Section 3.2 Key Protection Types.
*/
public final class KeyProtectionTypes {
/**
* This flag must be set if the authenticator uses software-based key management. Exclusive in authenticator
* metadata with KEY_PROTECTION_HARDWARE, KEY_PROTECTION_TEE, KEY_PROTECTION_SECURE_ELEMENT.
*/
public static final short KEY_PROTECTION_SOFTWARE = 1;
/**
* This flag should be set if the authenticator uses hardware-based key management. Exclusive in authenticator
* metadata with KEY_PROTECTION_SOFTWARE.
*/
public static final short KEY_PROTECTION_HARDWARE = 2;
/**
* This flag should be set if the authenticator uses the Trusted Execution Environment for key management. In
* authenticator metadata, this flag should be set in conjunction with KEY_PROTECTION_HARDWARE. Mutually exclusive
* in authenticator metadata with KEY_PROTECTION_SOFTWARE, KEY_PROTECTION_SECURE_ELEMENT.
*/
public static final short KEY_PROTECTION_TEE = 4;
/**
* This flag should be set if the authenticator uses a Secure Element for key management. In authenticator metadata,
* this flag should be set in conjunction with KEY_PROTECTION_HARDWARE. Mutually exclusive in authenticator metadata
* with KEY_PROTECTION_TEE, KEY_PROTECTION_SOFTWARE.
*/
public static final short KEY_PROTECTION_SECURE_ELEMENT = 8;
/**
* This flag must be set if the authenticator does not store (wrapped) UAuth keys at the client, but relies on a
* server-provided key handle. This flag must be set in conjunction with one of the other KEY_PROTECTION flags to
* indicate how the local key handle wrapping key and operations are protected. Servers may unset this flag in
* authenticator policy if they are not prepared to store and return key handles, for example, if they have a
* requirement to respond indistinguishably to authentication attempts against userIDs that do and do not exist.
* Refer to for more details.
*/
public static final short KEY_PROTECTION_REMOTE_HANDLE = 16;
}

View file

@ -0,0 +1,31 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.fido.fido2.api.common;
/**
* The method used by the authenticator to protect the matcher that performs user verification. Available values are
* defined in Section 3.3 Matcher Protection Types.
*/
public final class MatcherProtectionTypes {
/**
* This flag must be set if the authenticator's matcher is running in software. Exclusive in authenticator metadata
* with MATCHER_PROTECTION_TEE, MATCHER_PROTECTION_ON_CHIP.
*/
public static final short MATCHER_PROTECTION_SOFTWARE = 1;
/**
* This flag should be set if the authenticator's matcher is running inside the Trusted Execution Environment.
* Mutually exclusive in authenticator metadata with MATCHER_PROTECTION_SOFTWARE, MATCHER_PROTECTION_ON_CHIP.
*/
public static final short MATCHER_PROTECTION_TEE = 2;
/**
* This flag should be set if the authenticator's matcher is running on the chip. Mutually exclusive in
* authenticator metadata with MATCHER_PROTECTION_TEE, MATCHER_PROTECTION_SOFTWARE.
*/
public static final short MATCHER_PROTECTION_ON_CHIP = 4;
}

View file

@ -0,0 +1,45 @@
/*
* SPDX-FileCopyrightText: 2025 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.google.android.gms.fido.fido2.api.common;
import android.os.Parcel;
import androidx.annotation.NonNull;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import org.microg.gms.common.PublicApi;
import org.microg.gms.utils.ToStringHelper;
@PublicApi
@SafeParcelable.Class
public class PaymentExtension extends AbstractSafeParcelable {
@Field(value = 1, getterName = "isPayment")
private final boolean payment;
@Constructor
public PaymentExtension(@Param(1) boolean payment) {
this.payment = payment;
}
public boolean isPayment() {
return payment;
}
@Override
public String toString() {
return ToStringHelper.name("PaymentExtension").field("payment", payment).end();
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
CREATOR.writeToParcel(this, dest, flags);
}
public static final SafeParcelableCreatorAndWriter<PaymentExtension> CREATOR = AbstractSafeParcelable.findCreator(PaymentExtension.class);
}

View file

@ -0,0 +1,41 @@
/*
* SPDX-FileCopyrightText: 2025 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.google.android.gms.fido.fido2.api.common;
import android.os.Parcel;
import androidx.annotation.NonNull;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import org.microg.gms.common.PublicApi;
@PublicApi
@SafeParcelable.Class
public class PrfExtension extends AbstractSafeParcelable {
@Field(value = 1, getterName = "getEntries")
private final byte[][] entries;
@Constructor
public PrfExtension(@Param(1) byte[][] entries) {
this.entries = entries;
}
@NonNull
public byte[][] getEntries() {
return entries;
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
CREATOR.writeToParcel(this, dest, flags);
}
public static final SafeParcelableCreatorAndWriter<PrfExtension> CREATOR =
AbstractSafeParcelable.findCreator(PrfExtension.class);
}

View file

@ -0,0 +1,250 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.fido.fido2.api.common;
import android.os.Parcel;
import android.util.Base64;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableSerializer;
import org.microg.gms.common.Hide;
import org.microg.gms.common.PublicApi;
import org.microg.gms.utils.ToStringHelper;
import java.util.Arrays;
import java.util.Objects;
/**
* This class is contains the attributes that are returned to the caller when a new credential is created, or a new
* assertion is requested.
*/
@PublicApi
@SafeParcelable.Class
public class PublicKeyCredential extends AbstractSafeParcelable {
@Field(value = 1, getterName = "getId")
@NonNull
private String id;
@Field(value = 2, getterName = "getType")
@NonNull
private String type;
@Field(value = 3, getterName = "getRawId")
@NonNull
private byte[] rawId;
@Field(value = 4, getter = "$object.getResponse() instanceof $type ? ($type) $object.getResponse() : null")
@Nullable
private AuthenticatorAttestationResponse registerResponse;
@Field(value = 5, getter = "$object.getResponse() instanceof $type ? ($type) $object.getResponse() : null")
@Nullable
private AuthenticatorAssertionResponse signResponse;
@Field(value = 6, getter = "$object.getResponse() instanceof $type ? ($type) $object.getResponse() : null")
@Nullable
private AuthenticatorErrorResponse errorResponse;
@Field(value = 7, getterName = "getClientExtensionResults")
@Nullable
private AuthenticationExtensionsClientOutputs clientExtensionResults;
@Field(value = 8, getterName = "getAuthenticatorAttachment")
@Nullable
private String authenticatorAttachment;
PublicKeyCredential(@NonNull String id, @NonNull String type, @NonNull byte[] rawId, @NonNull AuthenticatorResponse response, @Nullable AuthenticationExtensionsClientOutputs clientExtensionResults, @Nullable String authenticatorAttachment) {
this(id, type, rawId, response instanceof AuthenticatorAttestationResponse ? (AuthenticatorAttestationResponse) response : null, response instanceof AuthenticatorAssertionResponse ? (AuthenticatorAssertionResponse) response : null, response instanceof AuthenticatorErrorResponse ? (AuthenticatorErrorResponse) response : null, clientExtensionResults, authenticatorAttachment);
}
@Constructor
PublicKeyCredential(@Param(1) @NonNull String id, @Param(2) @NonNull String type, @Param(3) @NonNull byte[] rawId, @Param(4) @Nullable AuthenticatorAttestationResponse registerResponse, @Param(5) @Nullable AuthenticatorAssertionResponse signResponse, @Param(6) @Nullable AuthenticatorErrorResponse errorResponse, @Param(7) @Nullable AuthenticationExtensionsClientOutputs clientExtensionResults, @Param(8) @Nullable String authenticatorAttachment) {
this.id = id;
this.type = type;
this.rawId = rawId;
this.registerResponse = registerResponse;
this.signResponse = signResponse;
this.errorResponse = errorResponse;
this.clientExtensionResults = clientExtensionResults;
this.authenticatorAttachment = authenticatorAttachment;
}
/**
* Returns the authenticator attachment of this credential.
*/
@Nullable
public String getAuthenticatorAttachment() {
return authenticatorAttachment;
}
@Nullable
public AuthenticationExtensionsClientOutputs getClientExtensionResults() {
return clientExtensionResults;
}
@NonNull
public String getId() {
return id;
}
@NonNull
public byte[] getRawId() {
return rawId;
}
public AuthenticatorResponse getResponse() {
if (registerResponse != null) return registerResponse;
if (signResponse != null) return signResponse;
if (errorResponse != null) return errorResponse;
throw new IllegalStateException("No response set.");
}
@NonNull
public String getType() {
return type;
}
/**
* Builder for {@link PublicKeyCredential}.
*/
public static class Builder {
@NonNull
private String id;
@NonNull
private byte[] rawId;
private AuthenticatorResponse response;
@Nullable
private AuthenticationExtensionsClientOutputs extensionsClientOutputs;
@Nullable
private String authenticatorAttachment;
/**
* The constructor of {@link PublicKeyCredential.Builder}.
*/
public Builder() {
}
/**
* Sets the output produced by the client's processing of the extensions requested by the relying party.
*/
public Builder setAuthenticationExtensionsClientOutputs(@Nullable AuthenticationExtensionsClientOutputs extensionsClientOutputs) {
this.extensionsClientOutputs = extensionsClientOutputs;
return this;
}
/**
* Sets the authenticator attachment of the credential.
*/
public Builder setAuthenticatorAttachment(@NonNull String authenticatorAttachment) {
this.authenticatorAttachment = authenticatorAttachment;
return this;
}
/**
* Sets the base64url encoding of the credential identifier.
*/
public Builder setId(@NonNull String id) {
this.id = id;
return this;
}
/**
* Sets the raw value of the credential identifier.
*/
public Builder setRawId(@NonNull byte[] rawId) {
this.rawId = rawId;
return this;
}
/**
* Sets the authenticator's response to the clients register or sign request.
* <p>
* This attribute contains the authenticator's response to the clients request to either create a public key
* credential, or generate an authentication assertion. If the {@link PublicKeyCredential} is created in
* response a register request, this attributes value will be an {@link AuthenticatorAttestationResponse},
* otherwise, the {@link PublicKeyCredential} was created in response to a sign request, and this attributes
* value will be an {@link AuthenticatorAssertionResponse}.
*/
public Builder setResponse(@NonNull AuthenticatorResponse response) {
this.response = response;
return this;
}
/**
* Builds the {@link PublicKeyCredential} object.
*/
public PublicKeyCredential build() {
return new PublicKeyCredential(id, PublicKeyCredentialType.PUBLIC_KEY.toString(), rawId, response, extensionsClientOutputs, authenticatorAttachment);
}
}
@NonNull
@Override
public String toString() {
String rawIdB64 = Base64.encodeToString(rawId, Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING);
return ToStringHelper.name("PublicKeyCredential")
.field("id", id)
.field("type", type)
.field("rawId", rawIdB64)
.field("registerResponse", registerResponse)
.field("signResponse", signResponse)
.field("errorResponse", errorResponse)
.field("clientExtensionResults", clientExtensionResults)
.field("authenticatorAttachment", authenticatorAttachment)
.end();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof PublicKeyCredential)) return false;
PublicKeyCredential that = (PublicKeyCredential) o;
if (!Objects.equals(id, that.id)) return false;
if (!Objects.equals(type, that.type)) return false;
if (!Arrays.equals(rawId, that.rawId)) return false;
if (!Objects.equals(registerResponse, that.registerResponse)) return false;
if (!Objects.equals(signResponse, that.signResponse)) return false;
if (!Objects.equals(errorResponse, that.errorResponse)) return false;
if (!Objects.equals(clientExtensionResults, that.clientExtensionResults)) return false;
return Objects.equals(authenticatorAttachment, that.authenticatorAttachment);
}
@Override
public int hashCode() {
return Arrays.hashCode(new Object[]{id, type, rawId, signResponse, registerResponse, errorResponse, clientExtensionResults, authenticatorAttachment});
}
/**
* Serializes the {@link PublicKeyCredential} to bytes. Use {@link #deserializeFromBytes(byte[])} to deserialize.
*
* @return the serialized byte array.
*/
@NonNull
public byte[] serializeToBytes() {
return SafeParcelableSerializer.serializeToBytes(this);
}
/**
* Deserializes the {@link PublicKeyCredential} from bytes, reversing {@link #serializeToBytes()}.
*
* @param serializedBytes The serialized bytes.
* @return The deserialized {@link PublicKeyCredential}.
*/
@NonNull
public static PublicKeyCredential deserializeFromBytes(byte[] serializedBytes) {
return SafeParcelableSerializer.deserializeFromBytes(serializedBytes, CREATOR);
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
CREATOR.writeToParcel(this, dest, flags);
}
@Hide
public static final SafeParcelableCreatorAndWriter<PublicKeyCredential> CREATOR = findCreator(PublicKeyCredential.class);
}

View file

@ -0,0 +1,341 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.google.android.gms.fido.fido2.api.common;
import android.os.Parcel;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableSerializer;
import org.microg.gms.common.Hide;
import org.microg.gms.common.PublicApi;
import org.microg.gms.utils.ToStringHelper;
import java.util.Arrays;
import java.util.List;
/**
* This class is used to supply options when creating a new credential.
*/
@PublicApi
@SafeParcelable.Class
public class PublicKeyCredentialCreationOptions extends RequestOptions {
@Field(value = 2, getterName = "getRp")
@NonNull
private PublicKeyCredentialRpEntity rp;
@Field(value = 3, getterName = "getUser")
@NonNull
private PublicKeyCredentialUserEntity user;
@Field(value = 4, getterName = "getChallenge")
@NonNull
private byte[] challenge;
@Field(value = 5, getterName = "getParameters")
@NonNull
private List<PublicKeyCredentialParameters> parameters;
@Field(value = 6, getterName = "getTimeoutSeconds")
@Nullable
private Double timeoutSeconds;
@Field(value = 7, getterName = "getExcludeList")
@Nullable
private List<PublicKeyCredentialDescriptor> excludeList;
@Field(value = 8, getterName = "getAuthenticatorSelection")
@Nullable
private AuthenticatorSelectionCriteria authenticatorSelection;
@Field(value = 9, getterName = "getRequestId")
@Nullable
private Integer requestId;
@Field(value = 10, getterName = "getTokenBinding")
@Nullable
private TokenBinding tokenBinding;
@Field(value = 11, getterName = "getAttestationConveyancePreference")
@Nullable
private AttestationConveyancePreference attestationConveyancePreference;
@Field(value = 12, getterName = "getAuthenticationExtensions")
@Nullable
private AuthenticationExtensions authenticationExtensions;
@Constructor
PublicKeyCredentialCreationOptions(@Param(2) @NonNull PublicKeyCredentialRpEntity rp, @Param(3) @NonNull PublicKeyCredentialUserEntity user, @Param(4) @NonNull byte[] challenge, @Param(5) @NonNull List<PublicKeyCredentialParameters> parameters, @Param(6) @Nullable Double timeoutSeconds, @Param(7) @Nullable List<PublicKeyCredentialDescriptor> excludeList, @Param(8) @Nullable AuthenticatorSelectionCriteria authenticatorSelection, @Param(9) @Nullable Integer requestId, @Param(10) @Nullable TokenBinding tokenBinding, @Param(11) @Nullable AttestationConveyancePreference attestationConveyancePreference, @Param(12) @Nullable AuthenticationExtensions authenticationExtensions) {
this.rp = rp;
this.user = user;
this.challenge = challenge;
this.parameters = parameters;
this.timeoutSeconds = timeoutSeconds;
this.excludeList = excludeList;
this.authenticatorSelection = authenticatorSelection;
this.requestId = requestId;
this.tokenBinding = tokenBinding;
this.attestationConveyancePreference = attestationConveyancePreference;
this.authenticationExtensions = authenticationExtensions;
}
@Nullable
public AttestationConveyancePreference getAttestationConveyancePreference() {
return attestationConveyancePreference;
}
@Nullable
public String getAttestationConveyancePreferenceAsString() {
if (attestationConveyancePreference == null) return null;
return attestationConveyancePreference.toString();
}
@Nullable
@Override
public AuthenticationExtensions getAuthenticationExtensions() {
return authenticationExtensions;
}
@Nullable
public AuthenticatorSelectionCriteria getAuthenticatorSelection() {
return authenticatorSelection;
}
@NonNull
@Override
public byte[] getChallenge() {
return challenge;
}
@Nullable
public List<PublicKeyCredentialDescriptor> getExcludeList() {
return excludeList;
}
@NonNull
public List<PublicKeyCredentialParameters> getParameters() {
return parameters;
}
@Nullable
@Override
public Integer getRequestId() {
return requestId;
}
@NonNull
public PublicKeyCredentialRpEntity getRp() {
return rp;
}
@Nullable
@Override
public Double getTimeoutSeconds() {
return timeoutSeconds;
}
@Nullable
@Override
public TokenBinding getTokenBinding() {
return tokenBinding;
}
@NonNull
public PublicKeyCredentialUserEntity getUser() {
return user;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof PublicKeyCredentialCreationOptions)) return false;
PublicKeyCredentialCreationOptions that = (PublicKeyCredentialCreationOptions) o;
if (rp != null ? !rp.equals(that.rp) : that.rp != null) return false;
if (user != null ? !user.equals(that.user) : that.user != null) return false;
if (!Arrays.equals(challenge, that.challenge)) return false;
if (parameters != null ? !parameters.equals(that.parameters) : that.parameters != null) return false;
if (timeoutSeconds != null ? !timeoutSeconds.equals(that.timeoutSeconds) : that.timeoutSeconds != null)
return false;
if (excludeList != null ? !excludeList.equals(that.excludeList) : that.excludeList != null) return false;
if (authenticatorSelection != null ? !authenticatorSelection.equals(that.authenticatorSelection) : that.authenticatorSelection != null)
return false;
if (requestId != null ? !requestId.equals(that.requestId) : that.requestId != null) return false;
if (tokenBinding != null ? !tokenBinding.equals(that.tokenBinding) : that.tokenBinding != null) return false;
if (attestationConveyancePreference != that.attestationConveyancePreference) return false;
return authenticationExtensions != null ? authenticationExtensions.equals(that.authenticationExtensions) : that.authenticationExtensions == null;
}
@Override
public int hashCode() {
return Arrays.hashCode(new Object[]{rp, user, Arrays.hashCode(challenge), parameters, timeoutSeconds, excludeList, authenticatorSelection, requestId, tokenBinding, attestationConveyancePreference, authenticationExtensions});
}
@Override
public String toString() {
return ToStringHelper.name("PublicKeyCredentialCreationOptions")
.field("rp", rp)
.field("user", user)
.field("challenge", challenge)
.field("parameters", parameters)
.field("timeoutSeconds", timeoutSeconds)
.field("excludeList", excludeList)
.field("authenticatorSelection", authenticatorSelection)
.field("requestId", requestId)
.field("tokenBinding", tokenBinding)
.field("attestationConveyancePreference", attestationConveyancePreference)
.field("authenticationExtensions", authenticationExtensions)
.end();
}
/**
* Builder for {@link PublicKeyCredentialCreationOptions}.
*/
public static class Builder {
@NonNull
private PublicKeyCredentialRpEntity rp;
@NonNull
private PublicKeyCredentialUserEntity user;
@NonNull
private byte[] challenge;
@NonNull
private List<PublicKeyCredentialParameters> parameters;
@Nullable
private Double timeoutSeconds;
@Nullable
private List<PublicKeyCredentialDescriptor> excludeList;
@Nullable
private AuthenticatorSelectionCriteria authenticatorSelection;
@Nullable
private Integer requestId;
@Nullable
private TokenBinding tokenBinding;
@Nullable
private AttestationConveyancePreference attestationConveyancePreference;
@Nullable
private AuthenticationExtensions authenticationExtensions;
/**
* The constructor of {@link PublicKeyCredentialCreationOptions.Builder}.
*/
public Builder() {
}
/**
* Sets the preference for obfuscation level of the returned attestation data.
*/
public Builder setAttestationConveyancePreference(@Nullable AttestationConveyancePreference attestationConveyancePreference) {
this.attestationConveyancePreference = attestationConveyancePreference;
return this;
}
/**
* Sets additional extensions that may dictate some client behavior during an exchange with a connected
* authenticator.
*/
public Builder setAuthenticationExtensions(@Nullable AuthenticationExtensions authenticationExtensions) {
this.authenticationExtensions = authenticationExtensions;
return this;
}
/**
* Sets constraints on the type of authenticator that is acceptable for this session.
*/
public Builder setAuthenticatorSelection(@Nullable AuthenticatorSelectionCriteria authenticatorSelection) {
this.authenticatorSelection = authenticatorSelection;
return this;
}
/**
* Sets the challenge to sign when generating the attestation for this request.
*/
public Builder setChallenge(@NonNull byte[] challenge) {
this.challenge = challenge;
return this;
}
/**
* Sets a list of credentials that, if found on a connected authenticator, will preclude registration of that
* authenticator with the relying party. This is often set to prevent re-registration of authenticators that
* the relying party has already registered on behalf of the user.
*/
public Builder setExcludeList(@Nullable List<PublicKeyCredentialDescriptor> excludeList) {
this.excludeList = excludeList;
return this;
}
/**
* Sets the {@link PublicKeyCredentialParameters} that constrain the type of credential to generate.
*/
public Builder setParameters(@NonNull List<PublicKeyCredentialParameters> parameters) {
this.parameters = parameters;
return this;
}
/**
* Sets the request id in order to link together events into a single session (the span of events between the
* time that the server initiates a single FIDO2 request to the client and receives reply) on a single device.
*/
public Builder setRequestId(@Nullable Integer requestId) {
this.requestId = requestId;
return this;
}
/**
* Sets information for a relying party, on whose behalf a given registration operation is being performed.
* <p>
* Note: the RpId should be an effective domain (aka, without scheme or port); and it should also be in secure
* context (aka https connection). Apps-facing API needs to check the package signature against Digital Asset
* Links, whose resource is the RP ID with prepended "//". Privileged (browser) API doesn't need the check.
*/
public Builder setRp(@NonNull PublicKeyCredentialRpEntity rp) {
this.rp = rp;
return this;
}
/**
* Sets a timeout that limits the duration of the registration session provided to the user.
*/
public Builder setTimeoutSeconds(@Nullable Double timeoutSeconds) {
this.timeoutSeconds = timeoutSeconds;
return this;
}
/**
* Sets the {@link TokenBinding} associated with the calling origin.
*/
public Builder setTokenBinding(@Nullable TokenBinding tokenBinding) {
this.tokenBinding = tokenBinding;
return this;
}
/**
* Sets information about the user on whose behalf the relying party is registering a credential.
*/
public Builder setUser(@NonNull PublicKeyCredentialUserEntity user) {
this.user = user;
return this;
}
/**
* Builds the {@link PublicKeyCredentialCreationOptions} object.
*/
public PublicKeyCredentialCreationOptions build() {
return new PublicKeyCredentialCreationOptions(rp, user, challenge, parameters, timeoutSeconds, excludeList, authenticatorSelection, requestId, tokenBinding, attestationConveyancePreference, authenticationExtensions);
}
}
/**
* Deserializes the {@link PublicKeyCredentialCreationOptions} from bytes, reversing {@link #serializeToBytes()}.
*
* @param serializedBytes The serialized bytes.
* @return The deserialized {@link PublicKeyCredentialCreationOptions}.
*/
@NonNull
public static PublicKeyCredentialCreationOptions deserializeFromBytes(byte[] serializedBytes) {
return SafeParcelableSerializer.deserializeFromBytes(serializedBytes, CREATOR);
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
CREATOR.writeToParcel(this, dest, flags);
}
@Hide
public static final SafeParcelableCreatorAndWriter<PublicKeyCredentialCreationOptions> CREATOR = findCreator(PublicKeyCredentialCreationOptions.class);
}

View file

@ -0,0 +1,127 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.fido.fido2.api.common;
import android.os.Parcel;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import com.google.android.gms.fido.common.Transport;
import org.microg.gms.common.PublicApi;
import org.microg.gms.utils.ToStringHelper;
import java.util.Arrays;
import java.util.List;
/**
* This class contains the attributes that are specified by a caller when referring to a credential as an input
* parameter to the registration or authentication method.
*/
@PublicApi
@SafeParcelable.Class
public class PublicKeyCredentialDescriptor extends AbstractSafeParcelable {
@Field(value = 2, getterName = "getType")
@NonNull
private PublicKeyCredentialType type;
@Field(value = 3, getterName = "getId")
@NonNull
private byte[] id;
@Field(value = 4, getterName = "getTransports")
@Nullable
private List<Transport> transports;
private PublicKeyCredentialDescriptor() {
}
public PublicKeyCredentialDescriptor(@NonNull String type, @NonNull byte[] id, @Nullable List<Transport> transports) {
try {
this.type = PublicKeyCredentialType.fromString(type);
} catch (PublicKeyCredentialType.UnsupportedPublicKeyCredTypeException e) {
throw new IllegalArgumentException(e);
}
this.id = id;
this.transports = transports;
}
@Constructor
PublicKeyCredentialDescriptor(@Param(2) @NonNull PublicKeyCredentialType type, @Param(3) @NonNull byte[] id, @Param(4) @Nullable List<Transport> transports) {
this.type = type;
this.id = id;
this.transports = transports;
}
@NonNull
public byte[] getId() {
return id;
}
@Nullable
public List<Transport> getTransports() {
return transports;
}
@NonNull
public PublicKeyCredentialType getType() {
return type;
}
@NonNull
public String getTypeAsString() {
return type.toString();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof PublicKeyCredentialDescriptor)) return false;
PublicKeyCredentialDescriptor that = (PublicKeyCredentialDescriptor) o;
if (type != that.type) return false;
if (!Arrays.equals(id, that.id)) return false;
return transports != null ? transports.equals(that.transports) : that.transports == null;
}
@Override
public int hashCode() {
return Arrays.hashCode(new Object[]{type, Arrays.hashCode(id), transports});
}
@Override
@NonNull
public String toString() {
return ToStringHelper.name("PublicKeyCredentialDescriptor")
.value(id)
.field("type", type)
.field("transports", transports)
.end();
}
/**
* Exception thrown when an unsupported or unrecognized public key credential descriptor is encountered.
*/
public static class UnsupportedPubKeyCredDescriptorException extends Exception {
public UnsupportedPubKeyCredDescriptorException(String message) {
super(message);
}
public UnsupportedPubKeyCredDescriptorException(String message, Throwable cause) {
super(message, cause);
}
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
CREATOR.writeToParcel(this, dest, flags);
}
public static final SafeParcelableCreatorAndWriter<PublicKeyCredentialDescriptor> CREATOR = findCreator(PublicKeyCredentialDescriptor.class);
}

View file

@ -0,0 +1,108 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.fido.fido2.api.common;
import android.os.Parcel;
import androidx.annotation.NonNull;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import org.microg.gms.common.Hide;
import org.microg.gms.common.PublicApi;
import org.microg.gms.utils.ToStringHelper;
import java.util.Arrays;
/**
* This class supplies additional parameters when creating a new credential.
*/
@PublicApi
@SafeParcelable.Class
public class PublicKeyCredentialParameters extends AbstractSafeParcelable {
@Field(value = 2, getterName = "getType")
@NonNull
private PublicKeyCredentialType type;
@Field(value = 3, getterName = "getAlgorithm")
@NonNull
private COSEAlgorithmIdentifier algorithm;
private PublicKeyCredentialParameters() {
}
public PublicKeyCredentialParameters(@NonNull String type, int algorithm) {
try {
this.type = PublicKeyCredentialType.fromString(type);
} catch (PublicKeyCredentialType.UnsupportedPublicKeyCredTypeException e) {
throw new IllegalArgumentException(e);
}
try {
this.algorithm = COSEAlgorithmIdentifier.fromCoseValue(algorithm);
} catch (COSEAlgorithmIdentifier.UnsupportedAlgorithmIdentifierException e) {
throw new IllegalArgumentException(e);
}
}
@Constructor
PublicKeyCredentialParameters(@Param(2) @NonNull PublicKeyCredentialType type, @Param(3) @NonNull COSEAlgorithmIdentifier algorithm) {
this.type = type;
this.algorithm = algorithm;
}
@NonNull
public COSEAlgorithmIdentifier getAlgorithm() {
return algorithm;
}
public int getAlgorithmIdAsInteger() {
return algorithm.toCoseValue();
}
@NonNull
public PublicKeyCredentialType getType() {
return type;
}
@NonNull
public String getTypeAsString() {
return type.toString();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof PublicKeyCredentialParameters)) return false;
PublicKeyCredentialParameters that = (PublicKeyCredentialParameters) o;
if (type != that.type) return false;
return algorithm != null ? algorithm.equals(that.algorithm) : that.algorithm == null;
}
@Override
public int hashCode() {
return Arrays.hashCode(new Object[]{type, algorithm});
}
@Override
@NonNull
public String toString() {
return ToStringHelper.name("PublicKeyCredentialParameters")
.field("type", type)
.field("algorithm", algorithm)
.end();
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
CREATOR.writeToParcel(this, dest, flags);
}
@Hide
public static final SafeParcelableCreatorAndWriter<PublicKeyCredentialParameters> CREATOR = findCreator(PublicKeyCredentialParameters.class);
}

View file

@ -0,0 +1,286 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.fido.fido2.api.common;
import android.os.Parcel;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableSerializer;
import org.microg.gms.common.Hide;
import org.microg.gms.common.PublicApi;
import org.microg.gms.utils.ToStringHelper;
import java.util.Arrays;
import java.util.List;
/**
* This class is used to supply an authentication request with the data it needs to generate an assertion.
*/
@PublicApi
@SafeParcelable.Class
public class PublicKeyCredentialRequestOptions extends RequestOptions {
@Field(value = 2, getterName = "getChallenge")
@NonNull
private byte[] challenge;
@Field(value = 3, getterName = "getTimeoutSeconds")
@Nullable
private Double timeoutSeconds;
@Field(value = 4, getterName = "getRpId")
@NonNull
private String rpId;
@Field(value = 5, getterName = "getAllowList")
@Nullable
private List<PublicKeyCredentialDescriptor> allowList;
@Field(value = 6, getterName = "getRequestId")
@Nullable
private Integer requestId;
@Field(value = 7, getterName = "getTokenBinding")
@Nullable
private TokenBinding tokenBinding;
@Field(value = 8, getterName = "getRequireUserVerification")
@Nullable
private UserVerificationRequirement requireUserVerification;
@Field(value = 9, getterName = "getAuthenticationExtensions")
@Nullable
private AuthenticationExtensions authenticationExtensions;
@Field(10)
@Nullable
Long longRequestId;
@Constructor
public PublicKeyCredentialRequestOptions(@Param(2)@NonNull byte[] challenge,@Param(3) @Nullable Double timeoutSeconds, @Param(4)@NonNull String rpId, @Param(5)@Nullable List<PublicKeyCredentialDescriptor> allowList,@Param(6) @Nullable Integer requestId,@Param(7) @Nullable TokenBinding tokenBinding,@Param(8) @Nullable UserVerificationRequirement requireUserVerification, @Param(9)@Nullable AuthenticationExtensions authenticationExtensions) {
this.challenge = challenge;
this.timeoutSeconds = timeoutSeconds;
this.rpId = rpId;
this.allowList = allowList;
this.requestId = requestId;
this.tokenBinding = tokenBinding;
this.requireUserVerification = requireUserVerification;
this.authenticationExtensions = authenticationExtensions;
}
@Nullable
public List<PublicKeyCredentialDescriptor> getAllowList() {
return allowList;
}
@Override
@Nullable
public AuthenticationExtensions getAuthenticationExtensions() {
return authenticationExtensions;
}
@Hide
@Nullable
public UserVerificationRequirement getRequireUserVerification() {
return requireUserVerification;
}
@Override
@NonNull
public byte[] getChallenge() {
return challenge;
}
@Override
@Nullable
public Integer getRequestId() {
return requestId;
}
@NonNull
public String getRpId() {
return rpId;
}
@Override
@Nullable
public Double getTimeoutSeconds() {
return timeoutSeconds;
}
@Override
@Nullable
public TokenBinding getTokenBinding() {
return tokenBinding;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof PublicKeyCredentialRequestOptions)) return false;
PublicKeyCredentialRequestOptions that = (PublicKeyCredentialRequestOptions) o;
if (!Arrays.equals(challenge, that.challenge)) return false;
if (timeoutSeconds != null ? !timeoutSeconds.equals(that.timeoutSeconds) : that.timeoutSeconds != null)
return false;
if (rpId != null ? !rpId.equals(that.rpId) : that.rpId != null) return false;
if (allowList != null ? !allowList.equals(that.allowList) : that.allowList != null) return false;
if (requestId != null ? !requestId.equals(that.requestId) : that.requestId != null) return false;
if (tokenBinding != null ? !tokenBinding.equals(that.tokenBinding) : that.tokenBinding != null) return false;
if (requireUserVerification != that.requireUserVerification) return false;
return authenticationExtensions != null ? authenticationExtensions.equals(that.authenticationExtensions) : that.authenticationExtensions == null;
}
@Override
public int hashCode() {
return Arrays.hashCode(new Object[]{Arrays.hashCode(challenge), timeoutSeconds, rpId, allowList, requestId, tokenBinding, requireUserVerification, authenticationExtensions});
}
@Override
@NonNull
public String toString() {
return ToStringHelper.name("PublicKeyCredentialRequestOptions")
.field("challenge", challenge)
.field("timeoutSeconds", timeoutSeconds)
.field("rpId", rpId)
.field("allowList", allowList)
.field("requestId", requestId)
.field("tokenBinding", tokenBinding)
.field("userVerificationRequirement", requireUserVerification)
.field("authenticationExtensions", authenticationExtensions)
.end();
}
/**
* Builder for {@link PublicKeyCredentialRequestOptions}.
*/
public static class Builder {
@NonNull
private byte[] challenge;
@Nullable
private Double timeoutSeconds;
@NonNull
private String rpId;
@Nullable
private List<PublicKeyCredentialDescriptor> allowList;
@Nullable
private Integer requestId;
@Nullable
private TokenBinding tokenBinding;
@Nullable
private AuthenticationExtensions authenticationExtensions;
@Nullable
private UserVerificationRequirement requireUserVerification;
/**
* The constructor of {@link PublicKeyCredentialRequestOptions.Builder}.
*/
public Builder() {
}
/**
* Sets a list of public key credentials which constrain authentication to authenticators that contain a
* private key for at least one of the supplied public keys.
*/
@NonNull
public Builder setAllowList(@Nullable List<PublicKeyCredentialDescriptor> allowList) {
this.allowList = allowList;
return this;
}
/**
* Sets additional extensions that may dictate some client behavior during an exchange with a connected
* authenticator.
*/
@NonNull
public Builder setAuthenticationExtensions(@Nullable AuthenticationExtensions authenticationExtensions) {
this.authenticationExtensions = authenticationExtensions;
return this;
}
/**
* Sets the nonce value that the authenticator should sign using a private key corresponding to a public key
* credential that is acceptable for this authentication session.
*/
@NonNull
public Builder setChallenge(@NonNull byte[] challenge) {
this.challenge = challenge;
return this;
}
/**
* Sets the request id in order to link together events into a single session (the span of events between the
* time that the server initiates a single FIDO2 request to the client and receives reply) on a single device.
* This field is optional.
*/
@NonNull
public Builder setRequestId(@Nullable Integer requestId) {
this.requestId = requestId;
return this;
}
@Hide
@NonNull
public Builder setRequireUserVerification(@Nullable UserVerificationRequirement requireUserVerification) {
this.requireUserVerification = requireUserVerification;
return this;
}
/**
* Sets identifier for a relying party, on whose behalf a given authentication operation is being performed.
* A public key credential can only be used for authentication with the same replying party it was registered
* with.
* <p>
* Note: the RpId should be an effective domain (aka, without scheme or port); and it should also be in secure
* context (aka https connection). Apps-facing API needs to check the package signature against Digital Asset
* Links, whose resource is the RP ID with prepended "//". Privileged (browser) API doesn't need the check.
*/
@NonNull
public Builder setRpId(@NonNull String rpId) {
this.rpId = rpId;
return this;
}
@NonNull
public Builder setTimeoutSeconds(@Nullable Double timeoutSeconds) {
this.timeoutSeconds = timeoutSeconds;
return this;
}
/**
* Sets the {@link TokenBinding} associated with the calling origin.
*/
@NonNull
public Builder setTokenBinding(@Nullable TokenBinding tokenBinding) {
this.tokenBinding = tokenBinding;
return this;
}
/**
* Builds the {@link PublicKeyCredentialRequestOptions} object.
*/
@NonNull
public PublicKeyCredentialRequestOptions build() {
return new PublicKeyCredentialRequestOptions(challenge, timeoutSeconds, rpId, allowList, requestId, tokenBinding, requireUserVerification, authenticationExtensions);
}
}
/**
* Deserializes the {@link PublicKeyCredentialRequestOptions} from bytes, reversing {@link #serializeToBytes()}.
*
* @param serializedBytes The serialized bytes.
* @return The deserialized {@link PublicKeyCredentialRequestOptions}.
*/
@NonNull
public static PublicKeyCredentialRequestOptions deserializeFromBytes(byte[] serializedBytes) {
return SafeParcelableSerializer.deserializeFromBytes(serializedBytes, CREATOR);
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
CREATOR.writeToParcel(this, dest, flags);
}
@Hide
public static final SafeParcelableCreatorAndWriter<PublicKeyCredentialRequestOptions> CREATOR = findCreator(PublicKeyCredentialRequestOptions.class);
}

View file

@ -0,0 +1,95 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.google.android.gms.fido.fido2.api.common;
import android.os.Parcel;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import org.microg.gms.common.Hide;
import org.microg.gms.common.PublicApi;
import org.microg.gms.utils.ToStringHelper;
import java.util.Arrays;
/**
* Represents the information about a relying party with which a credential is associated.
*/
@PublicApi
@SafeParcelable.Class
public class PublicKeyCredentialRpEntity extends AbstractSafeParcelable {
@Field(value = 2, getterName = "getId")
@NonNull
private String id;
@Field(value = 3, getterName = "getName")
@NonNull
private String name;
@Field(value = 4, getterName = "getIcon")
@Nullable
private String icon;
private PublicKeyCredentialRpEntity() {
}
@Constructor
public PublicKeyCredentialRpEntity(@Param(2)@NonNull String id, @Param(3)@NonNull String name, @Param(4)@Nullable String icon) {
this.id = id;
this.name = name;
this.icon = icon;
}
@Nullable
public String getIcon() {
return icon;
}
@NonNull
public String getId() {
return id;
}
@NonNull
public String getName() {
return name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof PublicKeyCredentialRpEntity)) return false;
PublicKeyCredentialRpEntity that = (PublicKeyCredentialRpEntity) o;
if (id != null ? !id.equals(that.id) : that.id != null) return false;
if (name != null ? !name.equals(that.name) : that.name != null) return false;
return icon != null ? icon.equals(that.icon) : that.icon == null;
}
@Override
public int hashCode() {
return Arrays.hashCode(new Object[]{id, name, icon});
}
@Override
@NonNull
public String toString() {
return ToStringHelper.name("PublicKeyCredentialRpEntity")
.value(id)
.field("name", name)
.field("icon", icon)
.end();
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
CREATOR.writeToParcel(this, dest, flags);
}
@Hide
public static final SafeParcelableCreatorAndWriter<PublicKeyCredentialRpEntity> CREATOR = findCreator(PublicKeyCredentialRpEntity.class);
}

View file

@ -0,0 +1,78 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.fido.fido2.api.common;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.NonNull;
import org.microg.gms.common.Hide;
import org.microg.gms.common.PublicApi;
/**
* This enumeration defines the valid credential types.
*/
public enum PublicKeyCredentialType implements Parcelable {
PUBLIC_KEY("public-key");
private final String value;
PublicKeyCredentialType(String value) {
this.value = value;
}
@Override
@NonNull
public String toString() {
return value;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(toString());
}
@Hide
public static PublicKeyCredentialType fromString(String type) throws UnsupportedPublicKeyCredTypeException {
for (PublicKeyCredentialType value : values()) {
if (value.value.equals(type)) return value;
}
throw new UnsupportedPublicKeyCredTypeException("PublicKeyCredentialType " + type + " not supported");
}
public static Creator<PublicKeyCredentialType> CREATOR = new Creator<PublicKeyCredentialType>() {
@Override
public PublicKeyCredentialType createFromParcel(Parcel source) {
try {
return PublicKeyCredentialType.fromString(source.readString());
} catch (UnsupportedPublicKeyCredTypeException e) {
throw new RuntimeException(e);
}
}
@Override
public PublicKeyCredentialType[] newArray(int size) {
return new PublicKeyCredentialType[size];
}
};
/**
* Exception thrown when an unsupported or unrecognized transport is encountered.
*/
public static class UnsupportedPublicKeyCredTypeException extends Exception {
public UnsupportedPublicKeyCredTypeException(String message) {
super(message);
}
}
}

View file

@ -0,0 +1,132 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.fido.fido2.api.common;
import android.os.Parcel;
import android.util.Base64;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import org.json.JSONException;
import org.json.JSONObject;
import org.microg.gms.common.Hide;
import org.microg.gms.common.PublicApi;
import org.microg.gms.utils.ToStringHelper;
import java.util.Arrays;
/**
* This class is used to supply additional parameters about the user account when creating a new Credential.
*/
@PublicApi
@SafeParcelable.Class
public class PublicKeyCredentialUserEntity extends AbstractSafeParcelable {
@Field(value = 2, getterName = "getId")
@NonNull
private byte[] id;
@Field(value = 3, getterName = "getName")
@NonNull
private String name;
@Field(value = 4, getterName = "getIcon")
@Nullable
private String icon;
@Field(value = 5, getterName = "getDisplayName")
@NonNull
private String displayName;
private PublicKeyCredentialUserEntity() {
}
public String toJson() throws JSONException {
JSONObject jsonObject = new JSONObject();
jsonObject.put("id", Base64.encodeToString(id, Base64.NO_WRAP | Base64.URL_SAFE | Base64.NO_PADDING));
jsonObject.put("name", name);
jsonObject.put("icon", icon);
jsonObject.put("displayName", displayName);
return jsonObject.toString();
}
public static PublicKeyCredentialUserEntity parseJson(String json) throws JSONException {
JSONObject jsonObject = new JSONObject(json);
byte[] id = Base64.decode(jsonObject.getString("id"), Base64.NO_WRAP | Base64.URL_SAFE | Base64.NO_PADDING);
String name = jsonObject.optString("name");
String icon = jsonObject.optString("icon");
String displayName = jsonObject.optString("displayName");
return new PublicKeyCredentialUserEntity(id, name, icon, displayName);
}
@Constructor
public PublicKeyCredentialUserEntity(@Param(2) @NonNull byte[] id, @Param(3) @NonNull String name, @Param(4) @Nullable String icon, @Param(5) @NonNull String displayName) {
this.id = id;
this.name = name;
this.icon = icon;
this.displayName = displayName;
}
@NonNull
public String getDisplayName() {
return displayName;
}
@Nullable
public String getIcon() {
return icon;
}
@NonNull
public byte[] getId() {
return id;
}
@NonNull
public String getName() {
return name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof PublicKeyCredentialUserEntity)) return false;
PublicKeyCredentialUserEntity that = (PublicKeyCredentialUserEntity) o;
if (!Arrays.equals(id, that.id)) return false;
if (name != null ? !name.equals(that.name) : that.name != null) return false;
if (icon != null ? !icon.equals(that.icon) : that.icon != null) return false;
return displayName != null ? displayName.equals(that.displayName) : that.displayName == null;
}
@Override
public int hashCode() {
return Arrays.hashCode(new Object[]{id, name, icon, displayName});
}
@Override
@NonNull
public String toString() {
return ToStringHelper.name("PublicKeyCredentialUserEntity")
.value(id)
.field("name", name)
.field("icon", icon)
.field("displayName", displayName)
.end();
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
CREATOR.writeToParcel(this, dest, flags);
}
@Hide
public static final SafeParcelableCreatorAndWriter<PublicKeyCredentialUserEntity> CREATOR = findCreator(PublicKeyCredentialUserEntity.class);
}

View file

@ -0,0 +1,64 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.fido.fido2.api.common;
import org.microg.gms.common.PublicApi;
/**
* Algorithm names and COSE identifiers for RSA (public) keys.
*/
@PublicApi
public enum RSAAlgorithm implements Algorithm {
/**
* RSASSA-PKCS1-v1_5 w/ SHA-256
*/
RS256(-257),
/**
* RSASSA-PKCS1-v1_5 w/ SHA-384
*/
RS384(-258),
/**
* RSASSA-PKCS1-v1_5 w/ SHA-512
*/
RS512(-259),
/**
* The legacy value for "RSASSA-PKCS1-v1_5 w/ SHA-1"
*
* @deprecated please use {@link #RS1} instead.
*/
@Deprecated
LEGACY_RS1(-262),
/**
* RSASSA-PSS w/ SHA-256
*/
PS256(-37),
/**
* RSASSA-PSS w/ SHA-384
*/
PS384(-38),
/**
* RSASSA-PSS w/ SHA-512
*/
PS512(-39),
/**
* RSASSA-PKCS1-v1_5 w/ SHA-1
*/
RS1(-65535);
private final int algoValue;
RSAAlgorithm(int algoValue) {
this.algoValue = algoValue;
}
@Override
public int getAlgoValue() {
return algoValue;
}
}

View file

@ -0,0 +1,40 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.fido.fido2.api.common;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableSerializer;
import org.microg.gms.common.PublicApi;
/**
* An abstract class representing FIDO2 request options.
*/
@PublicApi
public abstract class RequestOptions extends AbstractSafeParcelable {
@NonNull
public abstract byte[] getChallenge();
@Nullable
public abstract Double getTimeoutSeconds();
@Nullable
public abstract Integer getRequestId();
@Nullable
public abstract TokenBinding getTokenBinding();
@Nullable
public abstract AuthenticationExtensions getAuthenticationExtensions();
/**
* Serializes the {@link RequestOptions} to bytes. Use deserializeFromBytes(byte[]) to deserialize.
*/
@NonNull
public byte[] serializeToBytes() {
return SafeParcelableSerializer.serializeToBytes(this);
}
}

View file

@ -0,0 +1,86 @@
/*
* SPDX-FileCopyrightText: 2023 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.fido.fido2.api.common;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.NonNull;
/**
* An enum that describes the Resident Key (Discoverable Credential) requirements.
* <p>
* According to WebAuthn, this structure describes the Relying Party's requirements for client-side discoverable credentials
* (formerly known as resident credentials or resident keys):
* <p>
* If the resident key requirement is set to "required", then the Relying Party requires a client-side discoverable credential
* and is prepared to receive an error if it can't be created. If the resident key requirement is set to "preferred", the Relying
* party strongly prefers a client-side discoverable credential but will accept a server-side credential. If the resident key
* requirement is set to "discouraged" then a server-side credential is preferable, but will accept a client-side discoverable
* credential.
*/
public enum ResidentKeyRequirement implements Parcelable {
RESIDENT_KEY_DISCOURAGED("discouraged"),
RESIDENT_KEY_PREFERRED("preferred"),
RESIDENT_KEY_REQUIRED("required");
private final String requirement;
ResidentKeyRequirement(String requirement) {
this.requirement = requirement;
}
@NonNull
public static ResidentKeyRequirement fromString(@NonNull String requirement) throws UnsupportedResidentKeyRequirementException {
for (ResidentKeyRequirement value : values()) {
if (requirement.equals(value.requirement)) return value;
}
throw new UnsupportedResidentKeyRequirementException(requirement);
}
@Override
public int describeContents() {
return 0;
}
@NonNull
@Override
public String toString() {
return requirement;
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeString(requirement);
}
public static Creator<ResidentKeyRequirement> CREATOR = new Creator<ResidentKeyRequirement>() {
@Override
public ResidentKeyRequirement createFromParcel(Parcel source) {
try {
return ResidentKeyRequirement.fromString(source.readString());
} catch (UnsupportedResidentKeyRequirementException e) {
throw new RuntimeException(e);
}
}
@Override
public ResidentKeyRequirement[] newArray(int size) {
return new ResidentKeyRequirement[size];
}
};
/**
* Exception thrown when an unsupported or unrecognized resident key requirement is encountered.
*/
public static class UnsupportedResidentKeyRequirementException extends Exception {
public UnsupportedResidentKeyRequirementException(@NonNull String requirement) {
super("Resident key requirement " + requirement + " not supported");
}
}
}

View file

@ -0,0 +1,45 @@
/*
* SPDX-FileCopyrightText: 2025 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.google.android.gms.fido.fido2.api.common;
import android.os.Parcel;
import androidx.annotation.NonNull;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import org.microg.gms.common.PublicApi;
import org.microg.gms.utils.ToStringHelper;
@PublicApi
@SafeParcelable.Class
public class SimpleTransactionAuthorizationExtension extends AbstractSafeParcelable {
@Field(value = 1, getterName = "getText")
private final String text;
@Constructor
public SimpleTransactionAuthorizationExtension(@Param(1) String text) {
this.text = text;
}
public String getText() {
return text;
}
@Override
public String toString() {
return ToStringHelper.name("SimpleTransactionAuthorizationExtension").field("text", text).end();
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
CREATOR.writeToParcel(this, dest, flags);
}
public static final SafeParcelableCreatorAndWriter<SimpleTransactionAuthorizationExtension> CREATOR = AbstractSafeParcelable.findCreator(SimpleTransactionAuthorizationExtension.class);
}

View file

@ -0,0 +1,206 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.fido.fido2.api.common;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import org.json.JSONException;
import org.json.JSONObject;
import org.microg.gms.common.Hide;
import org.microg.gms.common.PublicApi;
import org.microg.gms.utils.ToStringHelper;
import java.util.Arrays;
/**
* Represents the Token binding information provided by the relying party.
*/
@PublicApi
@SafeParcelable.Class
public class TokenBinding extends AbstractSafeParcelable {
/**
* A singleton instance representing that token binding is not supported by the client.
*/
@NonNull
public static final TokenBinding NOT_SUPPORTED = new TokenBinding(TokenBindingStatus.NOT_SUPPORTED, null);
/**
* A singleton instance representing that token binding is supported by the client, but unused by the relying party.
*/
@NonNull
public static final TokenBinding SUPPORTED = new TokenBinding(TokenBindingStatus.SUPPORTED, null);
@Field(value = 2, getterName = "getTokenBindingStatus")
@NonNull
private TokenBindingStatus status;
@Field(value = 3, getterName = "getTokenBindingId")
@Nullable
private String tokenBindingId;
private TokenBinding() {
}
/**
* Constructs an instance of a {@link TokenBinding} for a provided token binding id.
*/
public TokenBinding(@Nullable String tokenBindingId) {
status = TokenBindingStatus.PRESENT;
this.tokenBindingId = tokenBindingId;
}
@Constructor
TokenBinding(@Param(2) @NonNull TokenBindingStatus status, @Param(3) @Nullable String tokenBindingId) {
this.status = status;
this.tokenBindingId = tokenBindingId;
}
/**
* Returns the token binding ID if the token binding status is {@code PRESENT}, otherwise returns null.
*/
@Nullable
public String getTokenBindingId() {
return tokenBindingId;
}
@Hide
@NonNull
public TokenBindingStatus getTokenBindingStatus() {
return status;
}
/**
* Returns the stringified {@link TokenBinding.TokenBindingStatus} associated with this instance.
*/
@NonNull
public String getTokenBindingStatusAsString() {
return status.toString();
}
/**
* Returns this {@link TokenBinding} object as a {@link JSONObject}.
*/
public JSONObject toJsonObject() {
try {
return new JSONObject().put("status", this.status).put("id", this.tokenBindingId);
} catch (JSONException e) {
throw new RuntimeException(e);
}
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof TokenBinding)) return false;
TokenBinding that = (TokenBinding) o;
if (status != that.status) return false;
return tokenBindingId != null ? tokenBindingId.equals(that.tokenBindingId) : that.tokenBindingId == null;
}
@Override
public int hashCode() {
return Arrays.hashCode(new Object[]{status, tokenBindingId});
}
@Override
@NonNull
public String toString() {
return ToStringHelper.name("TokenBinding")
.value(tokenBindingId)
.field("status", status)
.end();
}
/**
* The token binding status specified by the client.
*/
public enum TokenBindingStatus implements Parcelable {
/**
* The client supports token binding and the relying party is using it.
*/
PRESENT("present"),
/**
* The client supports token binding but the relying party is not using it.
*/
SUPPORTED("supported"),
/**
* The client does not support token binding.
*/
NOT_SUPPORTED("not-supported");
@NonNull
private final String value;
TokenBindingStatus(@NonNull String value) {
this.value = value;
}
@Hide
public static TokenBindingStatus fromString(String str) throws UnsupportedTokenBindingStatusException {
for (TokenBindingStatus value : values()) {
if (value.value.equals(str)) return value;
}
throw new UnsupportedTokenBindingStatusException("TokenBindingStatus " + str + " not supported");
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(value);
}
@Override
public int describeContents() {
return 0;
}
public static final Creator<TokenBindingStatus> CREATOR = new Creator<TokenBindingStatus>() {
@Override
public TokenBindingStatus createFromParcel(Parcel in) {
try {
return fromString(in.readString());
} catch (UnsupportedTokenBindingStatusException e) {
throw new RuntimeException(e);
}
}
@Override
public TokenBindingStatus[] newArray(int size) {
return new TokenBindingStatus[size];
}
};
@Override
@NonNull
public String toString() {
return value;
}
}
/**
* Exception thrown when an unsupported or unrecognized {@link TokenBinding.TokenBindingStatus} is encountered.
*/
public static class UnsupportedTokenBindingStatusException extends Exception {
public UnsupportedTokenBindingStatusException(String message) {
super(message);
}
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
CREATOR.writeToParcel(this, dest, flags);
}
@Hide
public static final SafeParcelableCreatorAndWriter<TokenBinding> CREATOR = findCreator(TokenBinding.class);
}

View file

@ -0,0 +1,66 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.fido.fido2.api.common;
import android.os.Parcel;
import androidx.annotation.NonNull;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import org.microg.gms.common.PublicApi;
import java.util.Arrays;
/**
* Extension for FIDO User Verification Method.
* <p>
* This authentication extension allows Relying Parties to ascertain the method(s) used by the user to authorize the
* operation.
* <p>
* Note that this extension can be used in only sign calls.
*/
@PublicApi
@SafeParcelable.Class
public class UserVerificationMethodExtension extends AbstractSafeParcelable {
@Field(value = 1, getterName = "getUvm")
@NonNull
private boolean uvm;
@Constructor
UserVerificationMethodExtension(@Param(1) boolean uvm) {
this.uvm = uvm;
}
@NonNull
public boolean getUvm() {
return uvm;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof UserVerificationMethodExtension)) return false;
UserVerificationMethodExtension that = (UserVerificationMethodExtension) o;
return uvm == that.uvm;
}
@Override
public int hashCode() {
return Arrays.hashCode(new Object[]{uvm});
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
CREATOR.writeToParcel(this, dest, flags);
}
public static final SafeParcelableCreatorAndWriter<UserVerificationMethodExtension> CREATOR = findCreator(UserVerificationMethodExtension.class);
}

View file

@ -0,0 +1,74 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.fido.fido2.api.common;
import org.microg.gms.common.PublicApi;
/**
* The authentication method/factor used by the authenticator to verify the user.
*/
@PublicApi
public final class UserVerificationMethods {
/**
* This flag must be set if the authenticator is able to confirm user presence in any fashion. If this flag and no
* other is set for user verification, the guarantee is only that the authenticator cannot be operated without some
* human intervention, not necessarily that the sensing of "presence" provides any level of user verification (e.g.
* a device that requires a button press to activate).
*/
public static final int USER_VERIFY_PRESENCE = 1;
/**
* This flag must be set if the authenticator uses any type of measurement of a fingerprint for user verification.
*/
public static final int USER_VERIFY_FINGERPRINT = 2;
/**
* This flag must be set if the authenticator uses a local-only passcode (i.e. a passcode not known by the server)
* for user verification.
*/
public static final int USER_VERIFY_PASSCODE = 4;
/**
* This flag must be set if the authenticator uses a voiceprint (also known as speaker recognition) for user
* verification.
*/
public static final int USER_VERIFY_VOICEPRINT = 8;
/**
* This flag must be set if the authenticator uses any manner of face recognition to verify the user.
*/
public static final int USER_VERIFY_FACEPRINT = 16;
/**
* This flag must be set if the authenticator uses any form of location sensor or measurement for user verification.
*/
public static final int USER_VERIFY_LOCATION = 32;
/**
* This flag must be set if the authenticator uses any form of eye biometrics for user verification.
*/
public static final int USER_VERIFY_EYEPRINT = 64;
/**
* This flag must be set if the authenticator uses a drawn pattern for user verification.
*/
public static final int USER_VERIFY_PATTERN = 128;
/**
* This flag must be set if the authenticator uses any measurement of a full hand (including palm-print, hand
* geometry or vein geometry) for user verification.
*/
public static final int USER_VERIFY_HANDPRINT = 256;
/**
* This flag must be set if the authenticator will respond without any user interaction (e.g. Silent Authenticator).
*/
public static final int USER_VERIFY_NONE = 512;
/**
* If an authenticator sets multiple flags for user verification types, it may also set this flag to indicate that
* all verification methods will be enforced (e.g. faceprint AND voiceprint). If flags for multiple user
* verification methods are set and this flag is not set, verification with only one is necessary (e.g. fingerprint
* OR passcode).
*/
public static final int USER_VERIFY_ALL = 1024;
private UserVerificationMethods() {
}
}

View file

@ -0,0 +1,69 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.google.android.gms.fido.fido2.api.common;
import android.os.Parcel;
import android.os.Parcelable;
import org.microg.gms.common.Hide;
import org.microg.gms.common.PublicApi;
public enum UserVerificationRequirement implements Parcelable {
REQUIRED("required"),
PREFERRED("preferred"),
DISCOURAGED("discouraged");
private final String value;
UserVerificationRequirement(String value) {
this.value = value;
}
@Override
public String toString() {
return value;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(toString());
}
@Hide
public static UserVerificationRequirement fromString(String attachment) throws UnsupportedUserVerificationRequirementException {
for (UserVerificationRequirement value : values()) {
if (value.value.equals(attachment)) return value;
}
throw new UnsupportedUserVerificationRequirementException("User verification requirement " + attachment + " not supported");
}
public static Creator<UserVerificationRequirement> CREATOR = new Creator<UserVerificationRequirement>() {
@Override
public UserVerificationRequirement createFromParcel(Parcel source) {
try {
return UserVerificationRequirement.fromString(source.readString());
} catch (UnsupportedUserVerificationRequirementException e) {
throw new RuntimeException(e);
}
}
@Override
public UserVerificationRequirement[] newArray(int size) {
return new UserVerificationRequirement[size];
}
};
public static class UnsupportedUserVerificationRequirementException extends Exception {
public UnsupportedUserVerificationRequirementException(String message) {
super(message);
}
}
}

View file

@ -0,0 +1,99 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.fido.fido2.api.common;
import android.os.Parcel;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import org.microg.gms.common.Hide;
import org.microg.gms.common.PublicApi;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
/**
* Represents up to three user verification methods used by the authenticator.
*/
@PublicApi
@SafeParcelable.Class
public class UvmEntries extends AbstractSafeParcelable {
@Field(value = 1, getterName = "getUvmEntryList")
@Nullable
private List<UvmEntry> uvmEntryList;
@Nullable
public List<UvmEntry> getUvmEntryList() {
return uvmEntryList;
}
@Constructor
UvmEntries(@Param(1) @Nullable List<UvmEntry> uvmEntryList) {
this.uvmEntryList = uvmEntryList;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof UvmEntries)) return false;
UvmEntries that = (UvmEntries) o;
if (uvmEntryList == null && that.uvmEntryList == null) return true;
if (uvmEntryList == null || that.uvmEntryList == null) return false;
return uvmEntryList.containsAll(that.uvmEntryList) && that.uvmEntryList.containsAll(uvmEntryList);
}
@Override
public int hashCode() {
return Arrays.hashCode(new Object[]{new HashSet<>(uvmEntryList)});
}
/**
* Builder for {@link UvmEntries}
*/
public static class Builder {
private List<UvmEntry> uvmEntryList = new ArrayList<>();
/**
* The constructor of {@link UvmEntries.Builder}.
*/
public Builder() {
}
public Builder addAll(@NonNull List<UvmEntry> uvmEntryList) {
if (this.uvmEntryList.size() + uvmEntryList.size() > 3) throw new IllegalStateException();
this.uvmEntryList.addAll(uvmEntryList);
return this;
}
public Builder addUvmEntry(@Nullable UvmEntry uvmEntry) {
if (uvmEntryList.size() >= 3) throw new IllegalStateException();
uvmEntryList.add(uvmEntry);
return this;
}
@NonNull
public UvmEntries build() {
return new UvmEntries(new ArrayList<>(uvmEntryList));
}
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
CREATOR.writeToParcel(this, dest, flags);
}
@Hide
public static SafeParcelableCreatorAndWriter<UvmEntries> CREATOR = findCreator(UvmEntries.class);
}

View file

@ -0,0 +1,105 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.fido.fido2.api.common;
import android.os.Parcel;
import androidx.annotation.NonNull;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import org.microg.gms.common.Hide;
import org.microg.gms.common.PublicApi;
import java.util.Arrays;
/**
* Represents a single User Verification Method Entry
*/
@PublicApi
@SafeParcelable.Class
public class UvmEntry extends AbstractSafeParcelable {
@Field(value = 1, getterName = "getUserVerificationMethod")
private int userVerificationMethod;
@Field(value = 2, getterName = "getKeyProtectionType")
private short keyProtectionType;
@Field(value = 3, getterName = "getMatcherProtectionType")
private short matcherProtectionType;
@Constructor
UvmEntry(@Param(1) int userVerificationMethod, @Param(2) short keyProtectionType, @Param(3) short matcherProtectionType) {
this.userVerificationMethod = userVerificationMethod;
this.keyProtectionType = keyProtectionType;
this.matcherProtectionType = matcherProtectionType;
}
public int getUserVerificationMethod() {
return userVerificationMethod;
}
public short getKeyProtectionType() {
return keyProtectionType;
}
public short getMatcherProtectionType() {
return matcherProtectionType;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof UvmEntry)) return false;
UvmEntry uvmEntry = (UvmEntry) o;
if (userVerificationMethod != uvmEntry.userVerificationMethod) return false;
if (keyProtectionType != uvmEntry.keyProtectionType) return false;
return matcherProtectionType == uvmEntry.matcherProtectionType;
}
@Override
public int hashCode() {
return Arrays.hashCode(new Object[]{userVerificationMethod, keyProtectionType, matcherProtectionType});
}
/**
* Builder for {@link UvmEntry}.
*/
public static class Builder {
private int userVerificationMethod;
private short keyProtectionType;
private short matcherProtectionType;
public Builder setUserVerificationMethod(int userVerificationMethod) {
this.userVerificationMethod = userVerificationMethod;
return this;
}
public Builder setKeyProtectionType(short keyProtectionType) {
this.keyProtectionType = keyProtectionType;
return this;
}
public Builder setMatcherProtectionType(short matcherProtectionType) {
this.matcherProtectionType = matcherProtectionType;
return this;
}
public UvmEntry build() {
return new UvmEntry(userVerificationMethod, keyProtectionType, matcherProtectionType);
}
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
CREATOR.writeToParcel(this, dest, flags);
}
@Hide
public static final SafeParcelableCreatorAndWriter<UvmEntry> CREATOR = findCreator(UvmEntry.class);
}

View file

@ -0,0 +1,49 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.fido.sourcedevice;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.ParcelFileDescriptor;
import com.google.android.gms.common.api.Api;
import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.common.api.HasApiKey;
import com.google.android.gms.tasks.Task;
import org.microg.gms.common.PublicApi;
/**
* The entry point for interacting with the FIDO SourceDirectTransfer APIs.
*/
@PublicApi
public interface SourceDirectTransferClient extends HasApiKey<Api.ApiOptions.NoOptions> {
/**
* The key used to retrieve {@link SourceDirectTransferResult} from the intent received by
* {@link Activity#onActivityResult(int, int, Intent)} after launching {@link PendingIntent} returned by
* {@link #startDirectTransfer(SourceStartDirectTransferOptions, ParcelFileDescriptor, ParcelFileDescriptor)}.
*/
String KEY_SOURCE_DIRECT_TRANSFER_RESULT = "source_direct_transfer_result";
/**
* Retrieves {@link SourceDirectTransferResult} from the intent received by
* {@link Activity#onActivityResult(int, int, Intent)} after launching {@link PendingIntent} returned by
* {@link #startDirectTransfer(SourceStartDirectTransferOptions, ParcelFileDescriptor, ParcelFileDescriptor)}.
*/
SourceDirectTransferResult getSourceDirectTransferResultFromIntent(Intent intent) throws ApiException;
/**
* Creates a Task with {@link PendingIntent}, which when started, will start direct transfer.
*
* @param input read side of pipe from the other device.
* @param output write side of pipe to the other device.
*/
Task<PendingIntent> startDirectTransfer(SourceStartDirectTransferOptions options, ParcelFileDescriptor input, ParcelFileDescriptor output);
}

View file

@ -0,0 +1,51 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.fido.sourcedevice;
import android.app.Activity;
import android.content.Intent;
import android.os.Parcel;
import androidx.annotation.NonNull;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
import org.microg.gms.common.PublicApi;
/**
* Result returned from the UI activity in {@link Activity#onActivityResult(int, int, Intent)} after the direct transfer finishes.
*/
@PublicApi
@SafeParcelable.Class
public class SourceDirectTransferResult extends AbstractSafeParcelable {
@Field(value = 1, getterName = "getStatus")
private Status status;
private SourceDirectTransferResult() {
}
@Constructor
public SourceDirectTransferResult(@Param(1) Status status) {
this.status = status;
}
/**
* Gets the {@link Status} from the returned {@link SourceDirectTransferResult}.
*/
public Status getStatus() {
return status;
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
CREATOR.writeToParcel(this, dest, flags);
}
public static final SafeParcelableCreatorAndWriter<SourceDirectTransferResult> CREATOR = findCreator(SourceDirectTransferResult.class);
}

View file

@ -0,0 +1,52 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.fido.sourcedevice;
import android.os.Parcel;
import androidx.annotation.NonNull;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
/**
* Customized options to start direct transfer.
*/
public class SourceStartDirectTransferOptions extends AbstractSafeParcelable {
/**
* Value of the callerType if the caller is unknown.
*/
public static final int CALLER_TYPE_UNKNOWN = 0;
/**
* Value of the callerType if the caller is browser.
*/
public static final int CALLER_TYPE_BROWSER = 2;
@Field(value = 1, getterName = "getCallerType")
private int callerType;
private SourceStartDirectTransferOptions() {
}
/**
* Constructor for the {@link SourceStartDirectTransferOptions}.
*/
public SourceStartDirectTransferOptions(@Param(1) int callerType) {
this.callerType = callerType;
}
public int getCallerType() {
return callerType;
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
CREATOR.writeToParcel(this, dest, flags);
}
public static final SafeParcelableCreatorAndWriter<SourceStartDirectTransferOptions> CREATOR = findCreator(SourceStartDirectTransferOptions.class);
}

View file

@ -0,0 +1,67 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.fido.u2f;
import android.app.Activity;
import android.content.Context;
import com.google.android.gms.common.api.Api;
import com.google.android.gms.common.api.GoogleApi;
import com.google.android.gms.fido.Fido;
import com.google.android.gms.tasks.Task;
/**
* The entry point for interacting with the regular app U2F APIs.
* <p>
* U2F (Universal Second Factor) is the name of the Security Key protocol in FIDO (Fast IDentity Online), which is the
* industry alliance where Security Keys are being standardized.
*
* @deprecated Please use {@link Fido} APIs instead.
*/
@Deprecated
public class U2fApiClient extends GoogleApi<Api.ApiOptions.NoOptions> {
private static final Api<Api.ApiOptions.NoOptions> API = null;
/**
* @param activity Calling {@link Activity}
*/
public U2fApiClient(Activity activity) {
super(activity, API, Api.ApiOptions.NO_OPTIONS);
throw new UnsupportedOperationException();
}
/**
* @param context The {@link Context} of the calling application
*/
public U2fApiClient(Context context) {
super(context, API, Api.ApiOptions.NO_OPTIONS);
throw new UnsupportedOperationException();
}
// /**
// * Creates a Task with {@link U2fPendingIntent}. When this Task object starts, it issues a U2F registration request,
// * which is done once per U2F device per account for associating the new U2F device with that account.
// *
// * @param requestParams for the registration request
// * @return Task with PendingIntent to launch U2F registration request
// */
// public Task<U2fPendingIntent> getRegisterIntent(RegisterRequestParams requestParams) {
// throw new UnsupportedOperationException();
// }
// /**
// * Creates a Task with U2fPendingIntent. When this Task object starts, it issues a U2F signing request for a relying party to authenticate a user.
// *
// * @param requestParams for the sign request
// * @return Task with PendingIntent to launch U2F signature request
// */
// public Task<U2fPendingIntent> getSignIntent(SignRequestParams requestParams) {
// throw new UnsupportedOperationException();
// }
}

View file

@ -0,0 +1,39 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.fido.u2f;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.IntentSender;
import com.google.android.gms.fido.Fido;
/**
* Interface for apps to launch a {@link PendingIntent}.
*
* @deprecated Please use {@link Fido} APIs instead.
*/
public interface U2fPendingIntent {
/**
* Returns true if an {@link Activity} has a {@link PendingIntent}.
*/
boolean hasPendingIntent();
/**
* Launches the PendingIntent.
*
* @param activity An Activity context to use to launch the intent. The activity's onActivityResult method will
* be invoked after the user is done.
* @param requestCode The request code to pass to onActivityResult.
* @throws IllegalStateException if hasPendingIntent is false
* @throws IntentSender.SendIntentException If the resolution intent has been canceled or is no longer able to
* execute the request.
*/
void launchPendingIntent(Activity activity, int requestCode);
}

View file

@ -0,0 +1,45 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package org.microg.gms.fido.fido2;
import android.content.Context;
import android.os.IBinder;
import android.os.RemoteException;
import com.google.android.gms.fido.fido2.api.IBooleanCallback;
import com.google.android.gms.fido.fido2.api.common.PublicKeyCredentialCreationOptions;
import com.google.android.gms.fido.fido2.api.common.PublicKeyCredentialRequestOptions;
import com.google.android.gms.fido.fido2.internal.regular.IFido2AppCallbacks;
import com.google.android.gms.fido.fido2.internal.regular.IFido2AppService;
import org.microg.gms.common.GmsClient;
import org.microg.gms.common.GmsService;
import com.google.android.gms.common.api.internal.ConnectionCallbacks;
import com.google.android.gms.common.api.internal.OnConnectionFailedListener;
public class Fido2GmsClient extends GmsClient<IFido2AppService> {
public Fido2GmsClient(Context context, ConnectionCallbacks callbacks, OnConnectionFailedListener connectionFailedListener) {
super(context, callbacks, connectionFailedListener, GmsService.FIDO2_REGULAR.ACTION);
serviceId = GmsService.FIDO2_REGULAR.SERVICE_ID;
}
public void getRegisterPendingIntent(IFido2AppCallbacks callbacks, PublicKeyCredentialCreationOptions options) throws RemoteException {
getServiceInterface().getRegisterPendingIntent(callbacks, options);
}
public void getSignPendingIntent(IFido2AppCallbacks callbacks, PublicKeyCredentialRequestOptions options) throws RemoteException {
getServiceInterface().getSignPendingIntent(callbacks, options);
}
public void isUserVerifyingPlatformAuthenticatorAvailable(IBooleanCallback callback) throws RemoteException {
getServiceInterface().isUserVerifyingPlatformAuthenticatorAvailable(callback);
}
@Override
protected IFido2AppService interfaceFromBinder(IBinder binder) {
return IFido2AppService.Stub.asInterface(binder);
}
}

View file

@ -0,0 +1,31 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package org.microg.gms.fido.fido2;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.IntentSender;
import com.google.android.gms.fido.fido2.Fido2PendingIntent;
public class Fido2PendingIntentImpl implements Fido2PendingIntent {
private PendingIntent pendingIntent;
public Fido2PendingIntentImpl(PendingIntent pendingIntent) {
this.pendingIntent = pendingIntent;
}
@Override
public boolean hasPendingIntent() {
return pendingIntent != null;
}
@Override
public void launchPendingIntent(Activity activity, int requestCode) throws IntentSender.SendIntentException {
if (!hasPendingIntent()) throw new IllegalStateException("No PendingIntent available");
activity.startIntentSenderForResult(pendingIntent.getIntentSender(), requestCode, null, 0, 0, 0);
}
}

View file

@ -0,0 +1,50 @@
/*
* SPDX-FileCopyrightText: 2022 microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package org.microg.gms.fido.fido2;
import android.content.Context;
import android.os.IBinder;
import android.os.RemoteException;
import com.google.android.gms.fido.fido2.api.IBooleanCallback;
import com.google.android.gms.fido.fido2.api.ICredentialListCallback;
import com.google.android.gms.fido.fido2.api.common.BrowserPublicKeyCredentialCreationOptions;
import com.google.android.gms.fido.fido2.api.common.BrowserPublicKeyCredentialRequestOptions;
import com.google.android.gms.fido.fido2.internal.privileged.IFido2PrivilegedCallbacks;
import com.google.android.gms.fido.fido2.internal.privileged.IFido2PrivilegedService;
import org.microg.gms.common.GmsClient;
import org.microg.gms.common.GmsService;
import com.google.android.gms.common.api.internal.ConnectionCallbacks;
import com.google.android.gms.common.api.internal.OnConnectionFailedListener;
public class Fido2PrivilegedGmsClient extends GmsClient<IFido2PrivilegedService> {
public Fido2PrivilegedGmsClient(Context context, ConnectionCallbacks callbacks, OnConnectionFailedListener connectionFailedListener) {
super(context, callbacks, connectionFailedListener, GmsService.FIDO2_PRIVILEGED.ACTION);
serviceId = GmsService.FIDO2_PRIVILEGED.SERVICE_ID;
}
public void getRegisterPendingIntent(IFido2PrivilegedCallbacks callbacks, BrowserPublicKeyCredentialCreationOptions options) throws RemoteException {
getServiceInterface().getRegisterPendingIntent(callbacks, options);
}
public void getSignPendingIntent(IFido2PrivilegedCallbacks callbacks, BrowserPublicKeyCredentialRequestOptions options) throws RemoteException {
getServiceInterface().getSignPendingIntent(callbacks, options);
}
public void isUserVerifyingPlatformAuthenticatorAvailable(IBooleanCallback callback) throws RemoteException {
getServiceInterface().isUserVerifyingPlatformAuthenticatorAvailable(callback);
}
public void getCredentialList(ICredentialListCallback callbacks, String rpId) throws RemoteException {
getServiceInterface().getCredentialList(callbacks, rpId);
}
@Override
protected IFido2PrivilegedService interfaceFromBinder(IBinder binder) {
return IFido2PrivilegedService.Stub.asInterface(binder);
}
}