Merge pull request #12108 from noahpistilli/kd-check-mail

IOS/KD: Implement NWC24_CHECK_MAIL_NOW
This commit is contained in:
Admiral H. Curtiss
2023-09-03 19:52:26 +02:00
committed by GitHub
16 changed files with 569 additions and 18 deletions

View File

@ -29,6 +29,8 @@ add_library(common
Crypto/bn.h
Crypto/ec.cpp
Crypto/ec.h
Crypto/HMAC.cpp
Crypto/HMAC.h
Crypto/SHA1.cpp
Crypto/SHA1.h
Debug/MemoryPatches.cpp

View File

@ -0,0 +1,27 @@
// Copyright 2023 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <mbedtls/hmac_drbg.h>
#include "Common/Crypto/HMAC.h"
#include "Common/ScopeGuard.h"
namespace Common::HMAC
{
bool HMACWithSHA1(std::span<const u8> key, std::span<const u8> msg, u8* out)
{
mbedtls_md_context_t ctx;
Common::ScopeGuard guard{[&ctx] { mbedtls_md_free(&ctx); }};
mbedtls_md_init(&ctx);
if (mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), 1))
return false;
if (mbedtls_md_hmac_starts(&ctx, key.data(), key.size()) ||
mbedtls_md_hmac_update(&ctx, msg.data(), msg.size()) || mbedtls_md_hmac_finish(&ctx, out))
{
return false;
}
return true;
}
} // namespace Common::HMAC

View File

@ -0,0 +1,14 @@
// Copyright 2023 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "Common/CommonTypes.h"
#include <span>
namespace Common::HMAC
{
// HMAC with the SHA1 message digest. Excepted output length is 20 bytes.
bool HMACWithSHA1(std::span<const u8> key, std::span<const u8> msg, u8* out);
} // namespace Common::HMAC

View File

@ -27,6 +27,7 @@ public:
explicit Impl(std::chrono::milliseconds timeout_ms, ProgressCallback callback);
bool IsValid() const;
std::string GetHeaderValue(std::string_view name) const;
void SetCookies(const std::string& cookies);
void UseIPv4();
void FollowRedirects(long max);
@ -41,6 +42,7 @@ public:
private:
static inline std::once_flag s_curl_was_initialized;
ProgressCallback m_callback;
Headers m_response_headers;
std::unique_ptr<CURL, decltype(&curl_easy_cleanup)> m_curl{nullptr, curl_easy_cleanup};
std::string m_error_string;
};
@ -82,6 +84,11 @@ s32 HttpRequest::GetLastResponseCode() const
return m_impl->GetLastResponseCode();
}
std::string HttpRequest::GetHeaderValue(std::string_view name) const
{
return m_impl->GetHeaderValue(name);
}
HttpRequest::Response HttpRequest::Get(const std::string& url, const Headers& headers,
AllowedReturnCodes codes)
{
@ -173,6 +180,17 @@ void HttpRequest::Impl::FollowRedirects(long max)
curl_easy_setopt(m_curl.get(), CURLOPT_MAXREDIRS, max);
}
std::string HttpRequest::Impl::GetHeaderValue(std::string_view name) const
{
for (const auto& [key, value] : m_response_headers)
{
if (key == name)
return value.value();
}
return {};
}
std::string HttpRequest::Impl::EscapeComponent(const std::string& string)
{
char* escaped = curl_easy_escape(m_curl.get(), string.c_str(), static_cast<int>(string.size()));
@ -190,10 +208,26 @@ static size_t CurlWriteCallback(char* data, size_t size, size_t nmemb, void* use
return actual_size;
}
static size_t header_callback(char* buffer, size_t size, size_t nitems, void* userdata)
{
auto* headers = static_cast<HttpRequest::Headers*>(userdata);
std::string_view full_buffer = std::string_view{buffer, nitems};
const size_t colon_pos = full_buffer.find(':');
if (colon_pos == std::string::npos)
return nitems * size;
const std::string_view key = full_buffer.substr(0, colon_pos);
const std::string_view value = StripWhitespace(full_buffer.substr(colon_pos + 1));
headers->emplace(std::string{key}, std::string{value});
return nitems * size;
}
HttpRequest::Response HttpRequest::Impl::Fetch(const std::string& url, Method method,
const Headers& headers, const u8* payload,
size_t size, AllowedReturnCodes codes)
{
m_response_headers.clear();
curl_easy_setopt(m_curl.get(), CURLOPT_POST, method == Method::POST);
curl_easy_setopt(m_curl.get(), CURLOPT_URL, url.c_str());
if (method == Method::POST)
@ -215,6 +249,9 @@ HttpRequest::Response HttpRequest::Impl::Fetch(const std::string& url, Method me
}
curl_easy_setopt(m_curl.get(), CURLOPT_HTTPHEADER, list);
curl_easy_setopt(m_curl.get(), CURLOPT_HEADERFUNCTION, header_callback);
curl_easy_setopt(m_curl.get(), CURLOPT_HEADERDATA, static_cast<void*>(&m_response_headers));
std::vector<u8> buffer;
curl_easy_setopt(m_curl.get(), CURLOPT_WRITEFUNCTION, CurlWriteCallback);
curl_easy_setopt(m_curl.get(), CURLOPT_WRITEDATA, &buffer);

View File

@ -40,6 +40,7 @@ public:
void FollowRedirects(long max = 1);
s32 GetLastResponseCode() const;
std::string EscapeComponent(const std::string& string);
std::string GetHeaderValue(std::string_view name) const;
Response Get(const std::string& url, const Headers& headers = {},
AllowedReturnCodes codes = AllowedReturnCodes::Ok_Only);
Response Post(const std::string& url, const std::vector<u8>& payload, const Headers& headers = {},

View File

@ -693,4 +693,9 @@ bool CaseInsensitiveEquals(std::string_view a, std::string_view b)
return std::equal(a.begin(), a.end(), b.begin(),
[](char ca, char cb) { return Common::ToLower(ca) == Common::ToLower(cb); });
}
std::string BytesToHexString(std::span<const u8> bytes)
{
return fmt::format("{:02x}", fmt::join(bytes, ""));
}
} // namespace Common

View File

@ -11,6 +11,7 @@
#include <iomanip>
#include <limits>
#include <locale>
#include <span>
#include <sstream>
#include <string>
#include <type_traits>
@ -313,4 +314,5 @@ std::string GetEscapedHtml(std::string html);
void ToLower(std::string* str);
void ToUpper(std::string* str);
bool CaseInsensitiveEquals(std::string_view a, std::string_view b);
std::string BytesToHexString(std::span<const u8> bytes);
} // namespace Common