|
@@ -17,6 +17,8 @@
|
|
|
|
|
|
|
|
namespace Service::AM::Applets {
|
|
namespace Service::AM::Applets {
|
|
|
|
|
|
|
|
|
|
+constexpr ResultCode ERROR_INVALID_PIN{ErrorModule::PCTL, 221};
|
|
|
|
|
+
|
|
|
static void LogCurrentStorage(AppletDataBroker& broker, std::string_view prefix) {
|
|
static void LogCurrentStorage(AppletDataBroker& broker, std::string_view prefix) {
|
|
|
std::unique_ptr<IStorage> storage = broker.PopNormalDataToApplet();
|
|
std::unique_ptr<IStorage> storage = broker.PopNormalDataToApplet();
|
|
|
for (; storage != nullptr; 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(const Core::Frontend::PhotoViewerApplet& frontend) : frontend(frontend) {}
|
|
|
|
|
|
|
|
PhotoViewer::~PhotoViewer() = default;
|
|
PhotoViewer::~PhotoViewer() = default;
|