syntax = "proto3";

package fido2;
option go_package=".;fido2";

import "patch/go.proto";

// Proto field names should be snake_case, but some plugins don't convert to 
// camel like they should, so we use camelCase here.

service FIDO2 {  
    rpc Devices(DevicesRequest) returns (DevicesResponse) {}
    rpc DeviceInfo(DeviceInfoRequest) returns (DeviceInfoResponse) {}
    rpc DeviceType(DeviceTypeRequest) returns (DeviceTypeResponse) {}
    rpc MakeCredential(MakeCredentialRequest) returns (MakeCredentialResponse) {}
    rpc SetPIN(SetPINRequest) returns (SetPINResponse) {}
    rpc Reset(ResetRequest) returns (ResetResponse) {}
    rpc RetryCount(RetryCountRequest) returns (RetryCountResponse) {}
    rpc Assertion(AssertionRequest) returns (AssertionResponse) {}
    rpc CredentialsInfo(CredentialsInfoRequest) returns (CredentialsInfoResponse) {}
    rpc Credentials(CredentialsRequest) returns (CredentialsResponse) {}
    rpc RelyingParties(RelyingPartiesRequest) returns (RelyingPartiesResponse) {}
    
    rpc GenerateHMACSecret(GenerateHMACSecretRequest) returns (GenerateHMACSecretResponse) {}
    rpc HMACSecret(HMACSecretRequest) returns (HMACSecretResponse) {}
}

message Device {
    string path = 1;
	int32 productId = 2 [(go.field) = {name: "ProductID"}];
	int32 vendorId = 3 [(go.field) = {name: "VendorID"}];
	string manufacturer = 4;
    string product = 5;
}

message Option {
    string name = 1;
    OptionValue value = 2;
}

message DeviceInfo {
    repeated string versions = 1;
    repeated string extensions = 2;
    string aaguid = 3 [(go.field) = {name: "AAGUID"}];
	repeated Option options = 4;
}

message RelyingParty {
    string id = 1 [(go.field) = {name: "ID"}];
    string name = 2;
}

enum DeviceType {
  option (go.enum) = {name: "DeviceType"};
  
  UNKNOWN_DEVICE = 0 [(go.value) = {name: "UnknownDevice"}];
  U2F_DEVICE = 1 [(go.value) = {name: "U2FDevice"}];
  FIDO2_DEVICE = 2 [(go.value) = {name: "FIDO2Device"}];  
}

message User {
    bytes id = 1 [(go.field) = {name: "ID"}];
    string name = 2;
    string displayName = 3;
    string icon = 4;
}

message Attestation {
	bytes clientDataHash = 1;
	bytes authData = 2;
	bytes credentialId = 3 [(go.field) = {name: "CredentialID"}];
	string credentialType = 4;
	bytes pubKey = 5;
	bytes cert = 6;
	bytes sig = 7;
	string format = 8;
}

message Credential {
	bytes id = 1 [(go.field) = {name: "ID"}];
	string type = 2;
    RelyingParty rp = 10 [(go.field) = {name: "RP"}];
	User user = 11;
}

message Assertion {
	bytes authData = 1;	
	bytes sig = 2;
    bytes hmacSecret = 3 [(go.field) = {name: "HMACSecret"}];
}

message CredentialsInfo {
	int32 rkExisting = 1 [(go.field) = {name: "RKExisting"}];
    int32 rkRemaining = 2 [(go.field) = {name: "RKRemaining"}];
}

message DevicesRequest {}
message DevicesResponse {
    repeated Device devices = 1;    
}

message DeviceTypeRequest {
    string device = 1;
}
message DeviceTypeResponse {
    DeviceType type = 1;
}

message DeviceInfoRequest {
    string device = 1;
}
message DeviceInfoResponse {
    DeviceInfo info = 1;
}

message MakeCredentialRequest {
    string device = 1;
    bytes clientDataHash = 2;
    RelyingParty rp = 3 [(go.field) = {name: "RP"}];
    User user = 4;
    string type = 5;
    string pin = 6 [(go.field) = {name: "PIN"}];
        
    repeated string extensions = 100;
    string rk = 101 [(go.field) = {name: "RK"}];
    string uv = 102 [(go.field) = {name: "UV"}];
}
message MakeCredentialResponse {
    Attestation attestation = 1;
}

message SetPINRequest {
    string device = 1;
    string pin = 2 [(go.field) = {name: "PIN"}];
    string oldPin = 3 [(go.field) = {name: "OldPIN"}];
} 
message SetPINResponse {}

message ResetRequest{
    string device = 1;
} 
message ResetResponse {}

message RetryCountRequest {
    string device = 1;
}
message RetryCountResponse {
    int32 count = 1;
}

message AssertionRequest {
    string device = 1;
    string rpId = 2 [(go.field) = {name: "RPID"}];
    bytes clientDataHash = 3;
    bytes credentialId = 4 [(go.field) = {name: "CredentialID"}];
    string pin = 5 [(go.field) = {name: "PIN"}];

    repeated string extensions = 100;
    string uv = 101 [(go.field) = {name: "UV"}];
    string up = 102 [(go.field) = {name: "UP"}];
    bytes hmacSalt = 103 [(go.field) = {name: "HMACSalt"}];
}
message AssertionResponse {
    Assertion assertion = 1;
}

message CredentialsInfoRequest {
    string device = 1;
    string pin = 2 [(go.field) = {name: "PIN"}];
}
message CredentialsInfoResponse {
    CredentialsInfo info = 1;
}

message CredentialsRequest {
    string device = 1;
    string rpId = 2 [(go.field) = {name: "RPID"}];
    string pin = 3 [(go.field) = {name: "PIN"}];
}
message CredentialsResponse {
    repeated Credential credentials = 1;
}

message RelyingPartiesRequest {
    string device = 1;
    string pin = 2 [(go.field) = {name: "PIN"}];
}
message RelyingPartiesResponse {
    repeated RelyingParty parties = 1;
}

enum OptionValue {
    option (go.enum) = {name: "OptionValue"};
  
    DEFAULT_OPTION = 0 [(go.value) = {name: "Default"}];
    TRUE = 1 [(go.value) = {name: "True"}];
    FALSE = 2 [(go.value) = {name: "False"}];
}

message GenerateHMACSecretRequest {
    string device = 1;
    string pin = 2 [(go.field) = {name: "PIN"}];
        
    bytes clientDataHash = 10;
    RelyingParty rp = 11 [(go.field) = {name: "RP"}];    
    User user = 12;

    OptionValue rk = 20 [(go.field) = {name: "RK"}];    
}
message GenerateHMACSecretResponse {        
    bytes credentialId = 2 [(go.field) = {name: "CredentialID"}];
}

message HMACSecretRequest {
    string device = 1;
    string pin = 2 [(go.field) = {name: "PIN"}];
    
    string rpId = 10 [(go.field) = {name: "RPID"}];
    bytes clientDataHash = 11;
    bytes credentialId = 12 [(go.field) = {name: "CredentialID"}];
    bytes salt = 13;
}
message HMACSecretResponse {
    bytes hmacSecret = 1 [(go.field) = {name: "HMACSecret"}];
}