applets: Implement Auth applet backend
This is responsible for parental controls and supports verifying, changing, and registering PIN codes.
This commit is contained in:
		@@ -17,6 +17,8 @@
 | 
			
		||||
 | 
			
		||||
namespace Service::AM::Applets {
 | 
			
		||||
 | 
			
		||||
constexpr ResultCode ERROR_INVALID_PIN{ErrorModule::PCTL, 221};
 | 
			
		||||
 | 
			
		||||
static void LogCurrentStorage(AppletDataBroker& broker, std::string_view prefix) {
 | 
			
		||||
    std::unique_ptr<IStorage> storage = broker.PopNormalDataToApplet();
 | 
			
		||||
    for (; storage != nullptr; storage = broker.PopNormalDataToApplet()) {
 | 
			
		||||
@@ -35,6 +37,120 @@ static void LogCurrentStorage(AppletDataBroker& broker, std::string_view prefix)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Auth::Auth(Core::Frontend::ParentalControlsApplet& frontend) : frontend(frontend) {}
 | 
			
		||||
 | 
			
		||||
Auth::~Auth() = default;
 | 
			
		||||
 | 
			
		||||
void Auth::Initialize() {
 | 
			
		||||
    Applet::Initialize();
 | 
			
		||||
    complete = false;
 | 
			
		||||
 | 
			
		||||
    const auto storage = broker.PopNormalDataToApplet();
 | 
			
		||||
    ASSERT(storage != nullptr);
 | 
			
		||||
    const auto data = storage->GetData();
 | 
			
		||||
    ASSERT(data.size() >= 0xC);
 | 
			
		||||
 | 
			
		||||
    struct Arg {
 | 
			
		||||
        INSERT_PADDING_BYTES(4);
 | 
			
		||||
        AuthAppletType type;
 | 
			
		||||
        u8 arg0;
 | 
			
		||||
        u8 arg1;
 | 
			
		||||
        u8 arg2;
 | 
			
		||||
        INSERT_PADDING_BYTES(1);
 | 
			
		||||
    };
 | 
			
		||||
    static_assert(sizeof(Arg) == 0xC, "Arg (AuthApplet) has incorrect size.");
 | 
			
		||||
 | 
			
		||||
    Arg arg{};
 | 
			
		||||
    std::memcpy(&arg, data.data(), sizeof(Arg));
 | 
			
		||||
 | 
			
		||||
    type = arg.type;
 | 
			
		||||
    arg0 = arg.arg0;
 | 
			
		||||
    arg1 = arg.arg1;
 | 
			
		||||
    arg2 = arg.arg2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Auth::TransactionComplete() const {
 | 
			
		||||
    return complete;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ResultCode Auth::GetStatus() const {
 | 
			
		||||
    return successful ? RESULT_SUCCESS : ERROR_INVALID_PIN;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Auth::ExecuteInteractive() {
 | 
			
		||||
    UNREACHABLE_MSG("Unexpected interactive applet data.");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Auth::Execute() {
 | 
			
		||||
    if (complete) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const auto unimplemented_log = [this] {
 | 
			
		||||
        UNIMPLEMENTED_MSG("Unimplemented Auth applet type for type={:08X}, arg0={:02X}, "
 | 
			
		||||
                          "arg1={:02X}, arg2={:02X}",
 | 
			
		||||
                          static_cast<u32>(type), arg0, arg1, arg2);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    switch (type) {
 | 
			
		||||
    case AuthAppletType::ShowParentalAuthentication: {
 | 
			
		||||
        const auto callback = [this](bool successful) { AuthFinished(successful); };
 | 
			
		||||
 | 
			
		||||
        if (arg0 == 1 && arg1 == 0 && arg2 == 1) {
 | 
			
		||||
            // ShowAuthenticatorForConfiguration
 | 
			
		||||
            frontend.VerifyPINForSettings(callback);
 | 
			
		||||
        } else if (arg1 == 0 && arg2 == 0) {
 | 
			
		||||
            // ShowParentalAuthentication(bool)
 | 
			
		||||
            frontend.VerifyPIN(callback, static_cast<bool>(arg0));
 | 
			
		||||
        } else {
 | 
			
		||||
            unimplemented_log();
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    case AuthAppletType::RegisterParentalPasscode: {
 | 
			
		||||
        const auto callback = [this] { AuthFinished(true); };
 | 
			
		||||
 | 
			
		||||
        if (arg0 == 0 && arg1 == 0 && arg2 == 0) {
 | 
			
		||||
            // RegisterParentalPasscode
 | 
			
		||||
            frontend.RegisterPIN(callback);
 | 
			
		||||
        } else {
 | 
			
		||||
            unimplemented_log();
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    case AuthAppletType::ChangeParentalPasscode: {
 | 
			
		||||
        const auto callback = [this] { AuthFinished(true); };
 | 
			
		||||
 | 
			
		||||
        if (arg0 == 0 && arg1 == 0 && arg2 == 0) {
 | 
			
		||||
            // ChangeParentalPasscode
 | 
			
		||||
            frontend.ChangePIN(callback);
 | 
			
		||||
        } else {
 | 
			
		||||
            unimplemented_log();
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    default:
 | 
			
		||||
        unimplemented_log();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Auth::AuthFinished(bool successful) {
 | 
			
		||||
    this->successful = successful;
 | 
			
		||||
 | 
			
		||||
    struct Return {
 | 
			
		||||
        ResultCode result_code;
 | 
			
		||||
    };
 | 
			
		||||
    static_assert(sizeof(Return) == 0x4, "Return (AuthApplet) has incorrect size.");
 | 
			
		||||
 | 
			
		||||
    Return return_{GetStatus()};
 | 
			
		||||
 | 
			
		||||
    std::vector<u8> out(sizeof(Return));
 | 
			
		||||
    std::memcpy(out.data(), &return_, sizeof(Return));
 | 
			
		||||
 | 
			
		||||
    broker.PushNormalDataFromApplet(IStorage{out});
 | 
			
		||||
    broker.SignalStateChanged();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PhotoViewer::PhotoViewer(const Core::Frontend::PhotoViewerApplet& frontend) : frontend(frontend) {}
 | 
			
		||||
 | 
			
		||||
PhotoViewer::~PhotoViewer() = default;
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,36 @@
 | 
			
		||||
 | 
			
		||||
namespace Service::AM::Applets {
 | 
			
		||||
 | 
			
		||||
enum class AuthAppletType : u32 {
 | 
			
		||||
    ShowParentalAuthentication,
 | 
			
		||||
    RegisterParentalPasscode,
 | 
			
		||||
    ChangeParentalPasscode,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class Auth final : public Applet {
 | 
			
		||||
public:
 | 
			
		||||
    explicit Auth(Core::Frontend::ParentalControlsApplet& frontend);
 | 
			
		||||
    ~Auth() override;
 | 
			
		||||
 | 
			
		||||
    void Initialize() override;
 | 
			
		||||
    bool TransactionComplete() const override;
 | 
			
		||||
    ResultCode GetStatus() const override;
 | 
			
		||||
    void ExecuteInteractive() override;
 | 
			
		||||
    void Execute() override;
 | 
			
		||||
 | 
			
		||||
    void AuthFinished(bool successful = true);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    Core::Frontend::ParentalControlsApplet& frontend;
 | 
			
		||||
    bool complete = false;
 | 
			
		||||
    bool successful = false;
 | 
			
		||||
 | 
			
		||||
    AuthAppletType type = AuthAppletType::ShowParentalAuthentication;
 | 
			
		||||
    u8 arg0 = 0;
 | 
			
		||||
    u8 arg1 = 0;
 | 
			
		||||
    u8 arg2 = 0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum class PhotoViewerAppletMode : u8 {
 | 
			
		||||
    CurrentApp = 0,
 | 
			
		||||
    AllApps = 1,
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user